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

Subversion Repositories hicovec

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 9 to Rev 10
    Reverse comparison

Rev 9 → Rev 10

/tags/arelease/debugger/clvpdbg.py
0,0 → 1,944
from pyparsing import *
import serial
 
#------------------------------------------------------------------------------------------------------
# CLASS STACK
#------------------------------------------------------------------------------------------------------
class Stack(object):
def __init__(self):
self.stack = []
def push(self, value):
self.stack.append(value)
def pop(self):
if len(self.stack) == 0:
return None
value = self.stack[-1]
del self.stack[-1]
return value
#------------------------------------------------------------------------------------------------------
# CLASS PROFILER
#------------------------------------------------------------------------------------------------------
class Profiler(object):
def __init__(self):
self.steps = 0
self.load = 0
self.store = 0
self.jumpbranch = 0
self.flag = 0
self.alu = 0
self.movmova = 0
self.vload = 0
self.vstore = 0
self.valu = 0
self.vmov = 0
self.shuffle = 0
self.scalar = 0
self.vector = 0
self.coopsimul = 0
def add(self, irval):
if irval == None:
return
self.steps = self.steps +1
s = False
v = False
#scalar cmd
if (irval & string.atoi("11100000000000000000000000000000",2)) != 0:
s = True
#vector cmd
if (irval & string.atoi("00000000000011100000000000000000",2)) != 0:
v = True
if s == True and v == True:
self.coopsimul = self.coopsimul + 1
else:
if s == True:
self.scalar = self.scalar + 1
if v == True:
self.vector = self.vector + 1
#alu cmd
if (irval & string.atoi("11000000000000000000000000000000",2))\
== string.atoi("01000000000000000000000000000000",2):
self.alu = self.alu +1
#jmp/jcc cmd
if (irval & string.atoi("11100000000000000000000000000000",2))\
== string.atoi("00100000000000000000000000000000",2):
self.jumpbranch = self.jumpbranch +1
#flag
if (irval & string.atoi("11000000000000000000000000000000",2))\
== string.atoi("11000000000000000000000000000000",2):
self.flag = self.flag +1
#load
if (irval & string.atoi("11110000000000000000000000000000",2))\
== string.atoi("10000000000000000000000000000000",2):
self.load = self.load +1
#store
if (irval & string.atoi("11110000000000000000000000000000",2))\
== string.atoi("10100000000000000000000000000000",2):
self.store = self.store +1
#vload
if (irval & string.atoi("11110000000000000000000000000000",2))\
== string.atoi("10010000000000000000000000000000",2):
self.vload = self.vload +1
 
#vstore
if (irval & string.atoi("11111100000000000000000000000000",2))\
== string.atoi("10110000000000000000000000000000",2):
self.vstore = self.vstore +1
#mov
if (irval & string.atoi("11111000000000000000000000000000",2))\
== string.atoi("10111000000000000000000000000000",2):
self.movmova = self.movmova +1
#mova
if (irval & string.atoi("11111100000000000000000000000000",2))\
== string.atoi("10110100000000000000000000000000",2):
self.movmova = self.movmova +1
#valu
if (irval & string.atoi("00000000000011000000000000000000",2))\
== string.atoi("00000000000001000000000000000000",2):
self.valu = self.valu +1
#vmov
if (irval & string.atoi("00000000000011100000000000000000",2))\
== string.atoi("00000000000000100000000000000000",2):
self.vmov = self.vmov +1
#vshuf
if (irval & string.atoi("00000000000011000000000000000000",2))\
== string.atoi("00000000000011000000000000000000",2):
self.shuffle = self.shuffle +1
def printanalysis(self):
if self.steps == 0:
print "No commands since reset"
return
print "Analysis of " + str(self.steps) + " commands is:"
print " " + "jumps / branches :".ljust(30," ") + str(self.jumpbranch).ljust(10," ") + self.toString(self.jumpbranch)
print " " + "flag modifications :".ljust(30," ") + str(self.flag).ljust(10," ") + self.toString(self.flag)
print " " + "scalar load :".ljust(30," ") + str(self.load).ljust(10," ") + self.toString(self.load)
print " " + "scalar store :".ljust(30," ") + str(self.store).ljust(10," ") + self.toString(self.store)
print " " + "vector load :".ljust(30," ") + str(self.vload).ljust(10," ")+ self.toString(self.vload)
print " " + "vector store :".ljust(30," ") + str(self.vstore).ljust(10," ")+ self.toString(self.vstore)
print " " + "scalar alu :".ljust(30," ") + str(self.alu).ljust(10," ")+ self.toString(self.alu)
print " " + "vector alu :".ljust(30," ") + str(self.valu).ljust(10," ")+ self.toString(self.valu)
print " " + "mov / mova :".ljust(30," ") + str(self.movmova).ljust(10," ")+ self.toString(self.movmova)
print " " + "vmov / vmol / vmor :".ljust(30," ") + str(self.vmov).ljust(10," ")+ self.toString(self.vmov)
print " " + "shuffle :".ljust(30," ") + str(self.shuffle).ljust(10," ")+ self.toString(self.shuffle)
print " " + "scalar commands :".ljust(30," ") + str(self.scalar).ljust(10," ")+ self.toString(self.scalar)
print " " + "vector commands :".ljust(30," ") + str(self.vector).ljust(10," ")+ self.toString(self.vector)
print " " + "cooperative / simultaneous :".ljust(30," ") + str(self.coopsimul).ljust(10," ")+ self.toString(self.coopsimul)
def toString(self, cmd):
val = float(cmd) * 100.0 / float(self.steps)
string = ("%.2f" % (val)).rjust(5," ") + " %"
return string
 
#------------------------------------------------------------------------------------------------------
# CLASS DEBUGGER
#------------------------------------------------------------------------------------------------------
class Debugger(object):
stack = Stack()
profiler = Profiler()
profiling = True
def __init__(self, args):
if len(args) > 3 or len(args) < 2:
print
print "usage: python clvpdbg.py portnumber [symboltablefilename]"
print
sys.exit(1)
if len(args) == 3:
symbols = self.getSymbols(args[2])
else:
symbols = None
self.shell(args[1], symbols)
def getSymbols(self, filename):
try:
file = open (filename,"r")
symbols = {}
for s in file.readlines():
x=s.replace("\n","").replace("\r","")
symbols[x.split(":")[1].upper()] = string.atoi(x.split(":")[0])
return symbols
except IOError:
print
print "error: unable to open symboltable file: " + filename
sys.exit(1)
def tointeger(self,s):
if s[0] == "$":
return string.atoi(s[1:], base = 16)
if s[0] == "%":
return string.atoi(s[1:], base = 2)
return string.atoi(s)
def shell(self, portnr, symbols):
try:
self.ser = ser = serial.Serial(string.atoi(portnr), 38400, 8, serial.PARITY_NONE, serial.STOPBITS_ONE, Settings().getTimeout(), 0, 0)
except serial.SerialException:
print
print "An error occured while trying to open the serial port"
sys.exit(1)
print "\nWelcome to the HiCoVec Debugger !!!\n\nEnter 'help' for a list of commands"
print
self.echo(True)
print
while(1):
sys.stdout.write("#")
line=sys.stdin.readline().upper()
if line.strip() != "":
try:
cmd = LineParser().parseLine(line)
if cmd.command == "QUIT" or cmd.command == "EXIT" or cmd.command == "Q":
sys.exit(0)
elif cmd.command == "HELP":
length = 23
print "The following commands are availiable:"
print " " + "C / CLOCK".ljust(length," ") + "-- generate one clock signal for cpu"
print " " + "R / RESET".ljust(length," ") + "-- reset cpu and trace stats"
print " " + "S / STEP [NUMBER]".ljust(length," ") + "-- execute NUMBER instructions"
print " " + "JUMP ADDRESS".ljust(length," ") + "-- execute until command at ADDRESS"
print " " + "M / DATA".ljust(length," ") + "-- display data of memory output"
print " " + "N / ADDR".ljust(length," ") + "-- display memory address line"
print " " + "A".ljust(length," ") + "-- display value of register A"
print " " + "X".ljust(length," ") + "-- display value of register X"
print " " + "Y".ljust(length," ") + "-- display value of register Y "
print " " + "I / IR".ljust(length," ") + "-- display value of instruction register "
print " " + "J / IC".ljust(length," ") + "-- display value of instruction counter "
print " " + "F / FLAGS".ljust(length," ") + "-- display value of various flags and signals"
print " " + "T / STATUS".ljust(length," ") + "-- display value of all registers"
print " " + "E / ECHO".ljust(length," ") + "-- test if device is responding"
print " " + "READ ADDRESS".ljust(length," ") + "-- read memory value at given ADDRESS"
print " " + "WRITE ADDRESS VALUE".ljust(length," ") + "-- write VALUE to given memory ADDRESS"
print " " + "DOWNLOAD ADDRESS COUNT".ljust(length," ") + "-- download data from memory into FILE"
print " " + "UPLOAD ADDRESS".ljust(length," ") + "-- upload data from FILE into memory"
print " " + "CCSTART ADDRESS".ljust(length," ") + "-- start counting clockticks to reach given ADDRESS"
print " " + "CCSTOP".ljust(length," ") + "-- aborts counting clockticks"
print " " + "CCSTATUS".ljust(length," ") + "-- displays clocktick counter status and value"
print " " + "TRACE [NUMBER]".ljust(length," ") + "-- display IC value of last NUMBER commands"
print " " + "PROFILE".ljust(length," ") + "-- show analysis of commands since reset"
print " " + "TOGGLEPROFILING".ljust(length," ") + "-- activate/deaktivate profiling"
print " " + "SYMBOLS".ljust(length," ") + "-- lists symbols imported from file"
print " " + "Q / QUIT / EXIT".ljust(length," ") + "-- exit debugger"
 
elif cmd.command == "SYMBOLS":
if symbols != None:
print "The following symbols are known:"
for k,v in sorted(symbols.iteritems()):
print " 0x" + str(hex(v))[2:].rjust(8,"0").upper() + " : " + k
else:
print "No symbol file given"
elif cmd.command == "CLOCK" or cmd.command == "C":
self.clock(True)
elif cmd.command == "RESET" or cmd.command == "R":
self.reset(True)
self.clock(False)
elif cmd.command == "A":
self.rega(True)
elif cmd.command == "X":
self.regx(True)
elif cmd.command == "Y":
self.regy(True)
elif cmd.command == "FLAGS" or cmd.command == "F":
self.flags(True)
elif cmd.command == "IR" or cmd.command == "I":
self.ir(True)
elif cmd.command == "IC" or cmd.command == "J":
self.ic(True)
elif cmd.command == "STEP" or cmd.command == "S":
if cmd.value != "":
self.step(self.tointeger(cmd.value), True, self.profiling)
else:
self.step(1, True)
elif cmd.command == "TRACE":
if cmd.value != "":
self.trace(self.tointeger(cmd.value))
else:
self.trace(10)
elif cmd.command == "PROFILE":
self.profiler.printanalysis();
elif cmd.command == "JUMP":
try:
if cmd.value:
address = self.tointeger(cmd.value)
else:
address = symbols[cmd.symbol]
self.jump(address, True, self.profiling)
except KeyError:
print "Symbol " + cmd.symbol + " is not known"
elif cmd.command == "WRITE":
try:
if cmd.newval_value:
newval = self.tointeger(cmd.newval_value)
else:
newval = symbols[cmd.newval_symbol]
try:
if cmd.value:
address = self.tointeger(cmd.value)
else:
address = symbols[cmd.symbol]
self.write(address, newval, True)
except KeyError:
print "Symbol " + cmd.symbol + " is not known"
except KeyError:
print "Symbol " + cmd.newval_symbol + " is not known"
elif cmd.command == "READ":
try:
if cmd.value:
address = self.tointeger(cmd.value)
else:
address = symbols[cmd.symbol]
self.read(address, True)
except KeyError:
print "Symbol " + cmd.symbol + " is not known"
 
elif cmd.command == "DOWNLOAD":
try:
if cmd.value:
address = self.tointeger(cmd.value)
else:
address = symbols[cmd.symbol]
sys.stdout.write("Enter filename: ")
filename=sys.stdin.readline().lstrip().rstrip()
self.download(address, self.tointeger(cmd.count), filename, True)
except KeyError:
print "Symbol " + cmd.symbol + " is not known"
elif cmd.command == "UPLOAD":
try:
if cmd.value:
address = self.tointeger(cmd.value)
else:
address = symbols[cmd.symbol]
sys.stdout.write("Enter filename: ")
filename=sys.stdin.readline().lstrip().rstrip()
self.upload(address, filename, True)
except KeyError:
print "Symbol " + cmd.symbol + " is not known"
elif cmd.command == "CCSTART":
try:
if cmd.value:
address = self.tointeger(cmd.value)
else:
address = symbols[cmd.symbol]
self.ccstart(address, True)
except KeyError:
print "Symbol " + cmd.symbol + " is not known"
elif cmd.command == "CCSTOP":
self.ccstop(True)
elif cmd.command == "CCSTATUS":
self.ccstatus(True)
 
elif cmd.command == "DATA" or cmd.command == "M":
self.data(True)
elif cmd.command == "ADDR" or cmd.command == "N":
self.addr(True)
elif cmd.command == "STATUS" or cmd.command == "T":
self.status(True)
elif cmd.command == "ECHO" or cmd.command == "E":
self.echo(True)
elif cmd.command == "GO" or cmd.command == "G":
self.go(True)
elif cmd.command == "PAUSE" or cmd.command == "P":
self.pause(True)
elif cmd.command == "TOGGLEPROFILING":
self.toggleprofiling()
except ParseException, err:
print "Unknown command or incorrect parameters"
print
def ccstop(self, verbose = True):
self.ser.write("5")
if self.ser.read(1) != "5":
if verbose == True:
print "Stop clock counter was NOT successful"
return False
if verbose == True:
print "Clock counter has been stopped"
return True
def ccstart(self, address, verbose = True):
if self.pause(False) == False:
if verbose == True:
print "Enter debugging-mode signal NOT accepted"
return False
if self.put("0", address, 0) == False:
if verbose == True:
print "Transmitting address was NOT successful"
return False
self.ser.write("4")
if self.ser.read(1) != "4":
if verbose == True:
print "Start clock counter was NOT successful"
return False
if verbose == True:
print "Clock counter has been started"
return True
def ccstatus(self, verbose = True):
self.ser.write("6")
status = self.ser.read(1)
if status != "":
if ord(status) == 1:
if verbose == True:
print "Counting clock cycles is finished"
else:
if verbose == True:
print "Counting clock cycles is NOT finished, yet"
else:
if verbose == True:
print "Request to get status was NOT successful"
return None
return self.get32BitReg("Clock cycles","7", verbose)
def toggleprofiling(self):
if self.profiling == False:
self.profiling = True
print "Profiling now ON"
else:
self.profiling = False
print "Profiling now OFF"
def upload(self, address, filename, verbose = True):
try:
f=open(filename,"rb")
i = 0
while f:
x3 = f.read(1)
x2 = f.read(1)
x1 = f.read(1)
x0 = f.read(1)
if x0 == "" or x1 == "" or x2 == "" or x3 == "":
f.close()
print "File has been uploaded"
return True
value = ord(x0) + ord(x1) * 256 + ord(x2) * 256 * 256 + ord(x3) * 256 * 256 * 256
trys = 0
done = False
s = Settings()
while trys < s.getRetrys() and done == False:
if self.write(address + i, value, False) == False:
trys = trys +1
else:
done = True
if done == False:
if verbose == True:
print "File has NOT been uploaded"
return False
i=i+1
 
except IOError:
print "File IO-error occured"
def download(self, address, count, filename, verbose = True):
try:
f=open(filename,"wb")
for i in range(count):
value = self.read(address + i, False)
if value == None:
if verbose == True:
print "Download was NOT successful"
return False
m = string.atoi("11111111000000000000000000000000",2)
for j in range(4):
a = (value & m) >> 8 * (3-j)
m = m >> 8
f.write(chr(a))
f.close()
print "Download into file " + filename + " was successful"
except IOError:
print "Unable to write file: " + filename
def read(self, address, verbose = True):
if self.put("0", address, 0) == False:
if verbose == True:
print "Transmitting address was NOT successful"
return None
return self.get32BitReg("value","2", verbose)
def write(self, address, value, verbose = True):
if self.put("0", address, 0) == False:
if verbose == True:
print "Transmitting address was NOT successful"
return False
if self.put("1", value, 0) == False:
if verbose == True:
print "Transmitting data was NOT successful"
return False
self.ser.write("3")
if self.ser.read(1) != "3":
if verbose == True:
print "Write was NOT successful"
return False
else:
if verbose == True:
print "Data has been written"
return True
def put(self, command, value, trys):
err = False
m = string.atoi("11111111000000000000000000000000",2)
self.ser.write(command)
if self.ser.read(1) != command:
return False
for i in range(4):
a = (value & m) >> 8 * (3-i)
m = m >> 8
self.ser.write(chr(a))
if ord(self.ser.read(1)) != a:
err = True
if err == True:
s= Settings()
if trys == s.getRetrys():
return False
return self.put(command, value, trys +1)
else:
return True
def echo(self, verbose = True):
self.ser.write("e")
if self.ser.read(1) == "e":
if verbose == True:
print "Device is responding"
return True
else:
if verbose == True:
print "Device is NOT responding"
return False
def go(self, verbose = True):
self.ser.write("g")
if self.ser.read(1) == "g":
if verbose == True:
print "System now in free-running-mode"
return True
else:
if verbose == True:
print "Enter free-running-mode signal NOT accepted"
return False
def pause(self, verbose = True):
self.ser.write("p")
if self.ser.read(1) == "p":
if verbose == True:
print "System now in debugging-mode"
return True
else:
if verbose == True:
print "Enter debugging-mode signal NOT accepted"
return False
def clock(self, verbose = True):
self.ser.write("c")
clock = self.ser.read(1)
try:
if ord(clock) == 255: #workaround for belkin usb-to-serial-adapter problems ...
return self.clock (verbose)
except TypeError:
if verbose == True:
print "Clock signal NOT accepted"
return False
if clock == "c":
if verbose == True:
print "Clock signal accepted"
return True
else:
if verbose == True:
print "Clock signal NOT accepted"
return False
def reset(self, verbose = True):
self.ser.write("r")
if self.ser.read(1) == "r":
self.stack = Stack();
self.profiler = Profiler()
if verbose == True:
print "Reset signal (CPU, trace, profiler) accepted"
return True
else:
if verbose == True:
print "Reset signal NOT accepted"
return False
def rega(self, verbose = True):
return self.get32BitReg("register a","a", verbose)
def regx(self, verbose = True):
return self.get32BitReg("register x","x", verbose)
def regy(self, verbose = True):
return self.get32BitReg("register y","y", verbose)
def ic(self, verbose = True):
return self.get32BitReg("instruction counter","j", verbose)
def ir(self, verbose = True):
return self.get32BitReg("instruction register","i", verbose)
def data(self, verbose = True):
return self.get32BitReg("memory output data","m", verbose)
def addr(self, verbose = True):
return self.get32BitReg("memory address signal","n", verbose)
def status(self, verbose = True):
return self.data(verbose), self.addr(verbose), self.ir(verbose), self.ic(verbose), self.rega(verbose),\
self.regx(verbose), self.regy(verbose), self.flags(verbose), \
def get32BitReg(self, name, command, verbose = True):
errors = 0
success = 0
while not success and errors < Settings().getRetrys():
self.ser.write(command)
x0=self.ser.read(1)
x1=self.ser.read(1)
x2=self.ser.read(1)
x3=self.ser.read(1)
checksum = self.ser.read(1)
if x0 == "" or x1 == "" or x2 == "" or x3 == "" or checksum == "":
errors = errors + 1
else:
if ord(checksum) != ord(x0) ^ ord(x1) ^ ord(x2) ^ ord(x3):
errors = errors +1
else:
success = 1
if success:
x = ord(x0) + 256 * ord(x1) + 256 * 256 * ord(x2) + 256 * 256 * 256 * ord(x3)
if verbose == True:
print name + ": 0x" + hex(ord(x3))[2:].rjust(2,"0").upper() + hex(ord(x2))[2:].rjust(2,"0").upper() \
+ hex(ord(x1))[2:].rjust(2,"0").upper() + hex(ord(x0))[2:].rjust(2,"0").upper()
return x
else:
print "request to get " + name + " was NOT successful"
return None
def flags(self, verbose = True):
self.ser.write("f")
flags = self.ser.read(1)
if flags != "":
ir_ready = int((ord(flags) & string.atoi("10000000",2)) > 0)
mem_ready = int((ord(flags) & string.atoi("01000000",2)) > 0)
mem_access = (ord(flags) & string.atoi("00111000",2)) >> 3
mem_access_0 = int((mem_access & 1) > 0)
mem_access_1 = int((mem_access & 2) > 0)
mem_access_2 = int((mem_access & 4) > 0)
halted = int((ord(flags) & string.atoi("00000100",2)) > 0)
zero = int((ord(flags) & string.atoi("00000010",2)) > 0)
carry = int((ord(flags) & string.atoi("00000001",2)) > 0)
if verbose == True:
print "ir_ready: " + str(ir_ready)
print "mem_ready: " + str(mem_ready)
print "mem_access: " + str(mem_access_2) + str(mem_access_1) + str(mem_access_0)
print "halted: " + str(halted)
print "zero: " + str(zero)
print "carry: " + str(carry)
return ir_ready, mem_ready, mem_access, halted, zero, carry
else:
print "Request to get flags was NOT successful"
return None
def step(self, steps, verbose = True, profile = True):
ticks = 0
ic = None
for i in range(steps):
ir_ready = 0
clocks = 0
 
while(ir_ready == 0):
if self.clock(False) == False:
text = "Device is not responding (Clock)"
if verbose == True:
print text
return 0, text, None
flags = self.flags(False)
if flags == None:
text = "Device is not responding (Flags)"
if verbose == True:
print text
return 0, text, None
else:
ir_ready, mem_ready, mem_access, halted, zero, carry = flags
clocks = clocks + 1
if clocks > Settings().getMaxClocks():
text = "Exceeded limit of " + str(Settings().getMaxClocks()) + " clock ticks for one command, aborting"
if verbose == True:
print text
return 0, text, None
ticks = ticks + clocks
ic = self.ic(False)
if profile == True:
self.profiler.add(self.ir(False))
if self.clock(False) == False:
text = "Device is not responding (Clock)"
if verbose == True:
print text
return 0, text, None
ticks = ticks + 1
self.stack.push(ic)
text = "Stepping "+ str(steps) +" command(s) successfull" + "\n" + "Required "+ str(ticks) + " clock ticks"
if verbose == True:
print text
return ticks, text, ic
def jump(self, address, verbose = True, profile = True):
ic = 0
steps = 0
ticks = 0
while(ic != address):
steps = steps +1
clocks, text, ic = self.step(1, False, profile)
if clocks == 0:
if verbose == True:
print "Step " + str(steps) + " was NOT successful"
print text
return 0
if ic == None:
if verbose == True:
print "Device is NOT responding (IC)"
return 0
if steps > Settings().getMaxSteps():
if verbose == True:
print "Exceeded limit of " + str(Settings().getMaxSteps()) + " steps, aborting"
return 0
ticks = ticks + clocks
 
if verbose == True:
print "Instruction counter value after " + str(steps) + " commands reached"
print "Required " + str(ticks) + " clock ticks"
return ticks
def trace(self,n):
print "trace of the last " + str(n) +" instruction counter values: "
import copy
newstack = copy.deepcopy(self.stack)
val = newstack.pop()
x = 0
while( val != None and x < n ):
print "0x" + hex(val)[2:].rjust(8,"0").upper()
val = newstack.pop()
x = x + 1
#------------------------------------------------------------------------------------------------------
# CLASS LINEPARSER
#------------------------------------------------------------------------------------------------------
class LineParser:
def parseLine(self,line):
expression = Forward()
dec_value = Word("0123456789", min=1)
hex_value = Word("$","ABCDEF0123456789", min=2)
bin_value = Word("%","10", min=2)
value = (dec_value ^ hex_value ^ bin_value).setResultsName("value")
ident = Word( alphas, alphanums + "_" ).setResultsName("symbol")
address = (value ^ ident).setResultsName("address")
newval_value = (dec_value ^ hex_value ^ bin_value).setResultsName("newval_value")
newval_ident = Word( alphas, alphanums + "_" ).setResultsName("newval_symbol")
newval_address = (newval_value ^ newval_ident).setResultsName("newval_address")
count = (dec_value ^ hex_value ^ bin_value).setResultsName("count")
cmd_1 = ( Keyword("C") ^ Keyword("CLOCK") ^ Keyword("RESET")^ Keyword("R") ^ Keyword("A") ^ Keyword("X") ^ Keyword("Y") \
^ Keyword("FLAGS") ^ Keyword("F") ^ Keyword("IR") ^ Keyword("IC") ^ Keyword("ECHO") ^ Keyword("QUIT") \
^ Keyword("Q") ^ Keyword("STATUS") ^ Keyword("E") ^ Keyword("HELP") ^ Keyword("EXIT") ^ Keyword("I") \
^ Keyword("J") ^ Keyword("T") ^ Keyword("M") ^Keyword("N") ^ Keyword("ADDR") ^ Keyword("DATA") \
^ Keyword("GO") ^ Keyword("PAUSE") ^ Keyword("G") ^ Keyword("P") ^ Keyword("SYMBOLS") ^ Keyword("PROFILE")
^ Keyword("TOGGLEPROFILING")).setResultsName("command")
cmd_2 = ((Keyword("STEP") ^ Keyword("S")).setResultsName("command")) ^ ((Keyword("STEP") ^ Keyword("S")).setResultsName("command") + value)
cmd_3 = Keyword("JUMP").setResultsName("command") + address
cmd_4 = ((Keyword("TRACE")).setResultsName("command")) ^ ((Keyword("TRACE")).setResultsName("command") + value)
cmd_5 = (Keyword("WRITE")).setResultsName("command") + address + newval_address
cmd_6 = (Keyword("READ")).setResultsName("command") + address
cmd_7 = (Keyword("UPLOAD")).setResultsName("command") + address
cmd_8 = (Keyword("DOWNLOAD")).setResultsName("command") + address + count
cmd_9 = (Keyword("CCSTART")).setResultsName("command") + address
cmd_10 = (Keyword("CCSTOP")).setResultsName("command")
cmd_11 = (Keyword("CCSTATUS")).setResultsName("command")
command = (cmd_1 ^ cmd_2 ^ cmd_3 ^ cmd_4 ^ cmd_5 ^ cmd_6 ^ cmd_7 ^ cmd_8 ^ cmd_9 ^ cmd_10 ^ cmd_11)
expression << command + lineEnd
result = expression.parseString(line)
return result
 
#------------------------------------------------------------------------------------------------------
# CLASS SETTINGS
#------------------------------------------------------------------------------------------------------
class Settings(object):
def getMaxClocks(self):
return 100
def getMaxSteps(self):
return 50000
def getRetrys(self):
return 15
def getTimeout(self):
return 0.1
#------------------------------------------------------------------------------------------------------
# MAIN PROGRAM
#------------------------------------------------------------------------------------------------------
if __name__ == '__main__':
import sys
Debugger(sys.argv)
/tags/arelease/debugger/readme.txt
0,0 → 1,3
there is a python library required for RS232 connection.
As its not liscensed under GPL you'll have to download it
yourself from: http://pyserial.sourceforge.net/
/tags/arelease/debugger/pyparsing.py
0,0 → 1,2942
# module pyparsing.py
#
# Copyright (c) 2003-2006 Paul T. McGuire
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
#from __future__ import generators
 
__doc__ = \
"""
pyparsing module - Classes and methods to define and execute parsing grammars
 
The pyparsing module is an alternative approach to creating and executing simple grammars,
vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you
don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
provides a library of classes that you use to construct the grammar directly in Python.
 
Here is a program to parse "Hello, World!" (or any greeting of the form "<salutation>, <addressee>!")::
 
from pyparsing import Word, alphas
# define grammar of a greeting
greet = Word( alphas ) + "," + Word( alphas ) + "!"
hello = "Hello, World!"
print hello, "->", greet.parseString( hello )
 
The program outputs the following::
 
Hello, World! -> ['Hello', ',', 'World', '!']
 
The Python representation of the grammar is quite readable, owing to the self-explanatory
class names, and the use of '+', '|' and '^' operators.
 
The parsed results returned from parseString() can be accessed as a nested list, a dictionary, or an
object with named attributes.
 
The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
- extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.)
- quoted strings
- embedded comments
"""
__version__ = "1.4.4-Mod-HaraldManske"
__versionTime__ = "19 October 2006 23:11"
__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>"
 
 
#Modified by Harald Manske:
# - removed Deprication Warning of Upcase class
# - created Downcase class
 
import string
import copy,sys
import warnings
import re
import sre_constants
import xml.sax.saxutils
#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
 
def _ustr(obj):
"""Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
then < returns the unicode object | encodes it with the default encoding | ... >.
"""
try:
# If this works, then _ustr(obj) has the same behaviour as str(obj), so
# it won't break any existing code.
return str(obj)
except UnicodeEncodeError, e:
# The Python docs (http://docs.python.org/ref/customization.html#l2h-182)
# state that "The return value must be a string object". However, does a
# unicode object (being a subclass of basestring) count as a "string
# object"?
# If so, then return a unicode object:
return unicode(obj)
# Else encode it... but how? There are many choices... :)
# Replace unprintables with escape codes?
#return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors')
# Replace unprintables with question marks?
#return unicode(obj).encode(sys.getdefaultencoding(), 'replace')
# ...
 
def _str2dict(strg):
return dict( [(c,0) for c in strg] )
#~ return set( [c for c in strg] )
 
class _Constants(object):
pass
alphas = string.lowercase + string.uppercase
nums = string.digits
hexnums = nums + "ABCDEFabcdef"
alphanums = alphas + nums
 
class ParseBaseException(Exception):
"""base exception class for all parsing runtime exceptions"""
__slots__ = ( "loc","msg","pstr","parserElement" )
# Performance tuning: we construct a *lot* of these, so keep this
# constructor as small and fast as possible
def __init__( self, pstr, loc, msg, elem=None ):
self.loc = loc
self.msg = msg
self.pstr = pstr
self.parserElement = elem
 
def __getattr__( self, aname ):
"""supported attributes by name are:
- lineno - returns the line number of the exception text
- col - returns the column number of the exception text
- line - returns the line containing the exception text
"""
if( aname == "lineno" ):
return lineno( self.loc, self.pstr )
elif( aname in ("col", "column") ):
return col( self.loc, self.pstr )
elif( aname == "line" ):
return line( self.loc, self.pstr )
else:
raise AttributeError, aname
 
def __str__( self ):
return "%s (at char %d), (line:%d, col:%d)" % ( self.msg, self.loc, self.lineno, self.column )
def __repr__( self ):
return _ustr(self)
def markInputline( self, markerString = ">!<" ):
"""Extracts the exception line from the input string, and marks
the location of the exception with a special symbol.
"""
line_str = self.line
line_column = self.column - 1
if markerString:
line_str = "".join( [line_str[:line_column], markerString, line_str[line_column:]])
return line_str.strip()
 
class ParseException(ParseBaseException):
"""exception thrown when parse expressions don't match class"""
"""supported attributes by name are:
- lineno - returns the line number of the exception text
- col - returns the column number of the exception text
- line - returns the line containing the exception text
"""
pass
class ParseFatalException(ParseBaseException):
"""user-throwable exception thrown when inconsistent parse content
is found; stops all parsing immediately"""
pass
 
class ReparseException(ParseBaseException):
def __init_( self, newstring, restartLoc ):
self.newParseText = newstring
self.reparseLoc = restartLoc
 
 
class RecursiveGrammarException(Exception):
"""exception thrown by validate() if the grammar could be improperly recursive"""
def __init__( self, parseElementList ):
self.parseElementTrace = parseElementList
def __str__( self ):
return "RecursiveGrammarException: %s" % self.parseElementTrace
 
class ParseResults(object):
"""Structured parse results, to provide multiple means of access to the parsed data:
- as a list (len(results))
- by list index (results[0], results[1], etc.)
- by attribute (results.<resultsName>)
"""
__slots__ = ( "__toklist", "__tokdict", "__doinit", "__name", "__parent", "__accumNames" )
def __new__(cls, toklist, name=None, asList=True, modal=True ):
if isinstance(toklist, cls):
return toklist
retobj = object.__new__(cls)
retobj.__doinit = True
return retobj
# Performance tuning: we construct a *lot* of these, so keep this
# constructor as small and fast as possible
def __init__( self, toklist, name=None, asList=True, modal=True ):
if self.__doinit:
self.__doinit = False
self.__name = None
self.__parent = None
self.__accumNames = {}
if isinstance(toklist, list):
self.__toklist = toklist[:]
else:
self.__toklist = [toklist]
self.__tokdict = dict()
 
# this line is related to debugging the asXML bug
#~ asList = False
if name:
if not modal:
self.__accumNames[name] = 0
if isinstance(name,int):
name = _ustr(name) # will always return a str, but use _ustr for consistency
self.__name = name
if not toklist in (None,'',[]):
if isinstance(toklist,basestring):
toklist = [ toklist ]
if asList:
if isinstance(toklist,ParseResults):
self[name] = (toklist.copy(),-1)
else:
self[name] = (ParseResults(toklist[0]),-1)
self[name].__name = name
else:
try:
self[name] = toklist[0]
except (KeyError,TypeError):
self[name] = toklist
 
def __getitem__( self, i ):
if isinstance( i, (int,slice) ):
return self.__toklist[i]
else:
if i not in self.__accumNames:
return self.__tokdict[i][-1][0]
else:
return ParseResults([ v[0] for v in self.__tokdict[i] ])
 
def __setitem__( self, k, v ):
if isinstance(v,tuple):
self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
sub = v[0]
elif isinstance(k,int):
self.__toklist[k] = v
sub = v
else:
self.__tokdict[k] = self.__tokdict.get(k,list()) + [(v,0)]
sub = v
if isinstance(sub,ParseResults):
sub.__parent = self
def __delitem__( self, i ):
if isinstance(i,(int,slice)):
del self.__toklist[i]
else:
del self._tokdict[i]
 
def __contains__( self, k ):
return self.__tokdict.has_key(k)
def __len__( self ): return len( self.__toklist )
def __nonzero__( self ): return len( self.__toklist ) > 0
def __iter__( self ): return iter( self.__toklist )
def keys( self ):
"""Returns all named result keys."""
return self.__tokdict.keys()
def items( self ):
"""Returns all named result keys and values as a list of tuples."""
return [(k,self[k]) for k in self.__tokdict.keys()]
def values( self ):
"""Returns all named result values."""
return [ v[-1][0] for v in self.__tokdict.values() ]
 
def __getattr__( self, name ):
if name not in self.__slots__:
if self.__tokdict.has_key( name ):
if name not in self.__accumNames:
return self.__tokdict[name][-1][0]
else:
return ParseResults([ v[0] for v in self.__tokdict[name] ])
else:
return ""
return None
 
def __add__( self, other ):
ret = self.copy()
ret += other
return ret
def __iadd__( self, other ):
if other.__tokdict:
offset = len(self.__toklist)
addoffset = ( lambda a: (a<0 and offset) or (a+offset) )
otheritems = other.__tokdict.items()
otherdictitems = [(k,(v[0],addoffset(v[1])) ) for (k,vlist) in otheritems for v in vlist]
for k,v in otherdictitems:
self[k] = v
if isinstance(v[0],ParseResults):
v[0].__parent = self
self.__toklist += other.__toklist
self.__accumNames.update( other.__accumNames )
del other
return self
def __repr__( self ):
return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
 
def __str__( self ):
out = "["
sep = ""
for i in self.__toklist:
if isinstance(i, ParseResults):
out += sep + _ustr(i)
else:
out += sep + repr(i)
sep = ", "
out += "]"
return out
 
def _asStringList( self, sep='' ):
out = []
for item in self.__toklist:
if out and sep:
out.append(sep)
if isinstance( item, ParseResults ):
out += item._asStringList()
else:
out.append( _ustr(item) )
return out
 
def asList( self ):
"""Returns the parse results as a nested list of matching tokens, all converted to strings."""
out = []
for res in self.__toklist:
if isinstance(res,ParseResults):
out.append( res.asList() )
else:
out.append( res )
return out
 
def asDict( self ):
"""Returns the named parse results as dictionary."""
return dict( self.items() )
 
def copy( self ):
"""Returns a new copy of a ParseResults object."""
ret = ParseResults( self.__toklist )
ret.__tokdict = self.__tokdict.copy()
ret.__parent = self.__parent
ret.__accumNames.update( self.__accumNames )
ret.__name = self.__name
return ret
def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
"""Returns the parse results as XML. Tags are created for tokens and lists that have defined results names."""
nl = "\n"
out = []
namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items() for v in vlist ] )
nextLevelIndent = indent + " "
# collapse out indents if formatting is not desired
if not formatted:
indent = ""
nextLevelIndent = ""
nl = ""
selfTag = None
if doctag is not None:
selfTag = doctag
else:
if self.__name:
selfTag = self.__name
if not selfTag:
if namedItemsOnly:
return ""
else:
selfTag = "ITEM"
out += [ nl, indent, "<", selfTag, ">" ]
worklist = self.__toklist
for i,res in enumerate(worklist):
if isinstance(res,ParseResults):
if i in namedItems:
out += [ res.asXML(namedItems[i], namedItemsOnly and doctag is None, nextLevelIndent,formatted)]
else:
out += [ res.asXML(None, namedItemsOnly and doctag is None, nextLevelIndent,formatted)]
else:
# individual token, see if there is a name for it
resTag = None
if i in namedItems:
resTag = namedItems[i]
if not resTag:
if namedItemsOnly:
continue
else:
resTag = "ITEM"
xmlBodyText = xml.sax.saxutils.escape(_ustr(res))
out += [ nl, nextLevelIndent, "<", resTag, ">", xmlBodyText, "</", resTag, ">" ]
out += [ nl, indent, "</", selfTag, ">" ]
return "".join(out)
 
def __lookup(self,sub):
for k,vlist in self.__tokdict.items():
for v,loc in vlist:
if sub is v:
return k
return None
def getName(self):
"""Returns the results name for this token expression."""
if self.__name:
return self.__name
elif self.__parent:
par = self.__parent
if par:
return par.__lookup(self)
else:
return None
elif (len(self) == 1 and
len(self.__tokdict) == 1 and
self.__tokdict.values()[0][0][1] in (0,-1)):
return self.__tokdict.keys()[0]
else:
return None
def dump(self,indent='',depth=0):
"""Diagnostic method for listing out the contents of a ParseResults.
Accepts an optional indent argument so that this string can be embedded
in a nested display of other data."""
out = []
out.append( indent+str(self.asList()) )
keys = self.items()
keys.sort()
for k,v in keys:
if out:
out.append('\n')
out.append( "%s%s- %s: " % (indent,(' '*depth), k) )
if isinstance(v,ParseResults):
if v.keys():
#~ out.append('\n')
out.append( v.dump(indent,depth+1) )
#~ out.append('\n')
else:
out.append(str(v))
else:
out.append(str(v))
#~ out.append('\n')
return "".join(out)
def col (loc,strg):
"""Returns current column within a string, counting newlines as line separators.
The first column is number 1.
"""
return (loc<len(strg) and strg[loc] == '\n') and 1 or loc - strg.rfind("\n", 0, loc)
 
def lineno(loc,strg):
"""Returns current line number within a string, counting newlines as line separators.
The first line is number 1.
"""
return strg.count("\n",0,loc) + 1
 
def line( loc, strg ):
"""Returns the line of text containing loc within a string, counting newlines as line separators.
"""
lastCR = strg.rfind("\n", 0, loc)
nextCR = strg.find("\n", loc)
if nextCR > 0:
return strg[lastCR+1:nextCR]
else:
return strg[lastCR+1:]
 
def _defaultStartDebugAction( instring, loc, expr ):
print "Match",expr,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )
 
def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
print "Matched",expr,"->",toks.asList()
def _defaultExceptionDebugAction( instring, loc, expr, exc ):
print "Exception raised:", exc
 
def nullDebugAction(*args):
"""'Do-nothing' debug action, to suppress debugging output during parsing."""
pass
 
class ParserElement(object):
"""Abstract base level parser element class."""
DEFAULT_WHITE_CHARS = " \n\t\r"
def setDefaultWhitespaceChars( chars ):
"""Overrides the default whitespace chars
"""
ParserElement.DEFAULT_WHITE_CHARS = chars
setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars)
def __init__( self, savelist=False ):
self.parseAction = list()
self.failAction = None
#~ self.name = "<unknown>" # don't define self.name, let subclasses try/except upcall
self.strRepr = None
self.resultsName = None
self.saveAsList = savelist
self.skipWhitespace = True
self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
self.copyDefaultWhiteChars = True
self.mayReturnEmpty = False
self.keepTabs = False
self.ignoreExprs = list()
self.debug = False
self.streamlined = False
self.mayIndexError = True
self.errmsg = ""
self.modalResults = True
self.debugActions = ( None, None, None )
self.re = None
 
def copy( self ):
"""Make a copy of this ParserElement. Useful for defining different parse actions
for the same parsing pattern, using copies of the original parse element."""
cpy = copy.copy( self )
cpy.parseAction = self.parseAction[:]
cpy.ignoreExprs = self.ignoreExprs[:]
if self.copyDefaultWhiteChars:
cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
return cpy
 
def setName( self, name ):
"""Define name for this expression, for use in debugging."""
self.name = name
self.errmsg = "Expected " + self.name
return self
 
def setResultsName( self, name, listAllMatches=False ):
"""Define name for referencing matching tokens as a nested attribute
of the returned parse results.
NOTE: this returns a *copy* of the original ParserElement object;
this is so that the client can define a basic element, such as an
integer, and reference it in multiple places with different names.
"""
newself = self.copy()
newself.resultsName = name
newself.modalResults = not listAllMatches
return newself
 
def normalizeParseActionArgs( f ):
"""Internal method used to decorate parse actions that take fewer than 3 arguments,
so that all parse actions can be called as f(s,l,t)."""
STAR_ARGS = 4
 
try:
restore = None
if isinstance(f,type):
restore = f
f = f.__init__
if f.func_code.co_flags & STAR_ARGS:
return f
numargs = f.func_code.co_argcount
if hasattr(f,"im_self"):
numargs -= 1
if restore:
f = restore
except AttributeError:
try:
# not a function, must be a callable object, get info from the
# im_func binding of its bound __call__ method
if f.__call__.im_func.func_code.co_flags & STAR_ARGS:
return f
numargs = f.__call__.im_func.func_code.co_argcount
if hasattr(f.__call__,"im_self"):
numargs -= 1
except AttributeError:
# not a bound method, get info directly from __call__ method
if f.__call__.func_code.co_flags & STAR_ARGS:
return f
numargs = f.__call__.func_code.co_argcount
if hasattr(f.__call__,"im_self"):
numargs -= 1
 
#~ print "adding function %s with %d args" % (f.func_name,numargs)
if numargs == 3:
return f
else:
if numargs == 2:
def tmp(s,l,t):
return f(l,t)
elif numargs == 1:
def tmp(s,l,t):
return f(t)
else: #~ numargs == 0:
def tmp(s,l,t):
return f()
return tmp
normalizeParseActionArgs = staticmethod(normalizeParseActionArgs)
def setParseAction( self, *fns ):
"""Define action to perform when successfully matching parse element definition.
Parse action fn is a callable method with 0-3 arguments, called as fn(s,loc,toks),
fn(loc,toks), fn(toks), or just fn(), where:
- s = the original string being parsed
- loc = the location of the matching substring
- toks = a list of the matched tokens, packaged as a ParseResults object
If the functions in fns modify the tokens, they can return them as the return
value from fn, and the modified list of tokens will replace the original.
Otherwise, fn does not need to return any value."""
self.parseAction = map(self.normalizeParseActionArgs, list(fns))
return self
 
def addParseAction( self, *fns ):
"""Add parse action to expression's list of parse actions. See setParseAction_."""
self.parseAction += map(self.normalizeParseActionArgs, list(fns))
return self
 
def setFailAction( self, fn ):
"""Define action to perform if parsing fails at this expression.
Fail acton fn is a callable function that takes the arguments
fn(s,loc,expr,err) where:
- s = string being parsed
- loc = location where expression match was attempted and failed
- expr = the parse expression that failed
- err = the exception thrown
The function returns no value. It may throw ParseFatalException
if it is desired to stop parsing immediately."""
self.failAction = fn
return self
def skipIgnorables( self, instring, loc ):
exprsFound = True
while exprsFound:
exprsFound = False
for e in self.ignoreExprs:
try:
while 1:
loc,dummy = e._parse( instring, loc )
exprsFound = True
except ParseException:
pass
return loc
 
def preParse( self, instring, loc ):
if self.ignoreExprs:
loc = self.skipIgnorables( instring, loc )
if self.skipWhitespace:
wt = self.whiteChars
instrlen = len(instring)
while loc < instrlen and instring[loc] in wt:
loc += 1
return loc
 
def parseImpl( self, instring, loc, doActions=True ):
return loc, []
 
def postParse( self, instring, loc, tokenlist ):
return tokenlist
 
#~ @profile
def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
debugging = ( self.debug ) #and doActions )
 
if debugging or self.failAction:
#~ print "Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )
if (self.debugActions[0] ):
self.debugActions[0]( instring, loc, self )
if callPreParse:
preloc = self.preParse( instring, loc )
else:
preloc = loc
tokensStart = loc
try:
try:
loc,tokens = self.parseImpl( instring, preloc, doActions )
except IndexError:
raise ParseException( instring, len(instring), self.errmsg, self )
#~ except ReparseException, retryEx:
#~ pass
except ParseException, err:
#~ print "Exception raised:", err
if self.debugActions[2]:
self.debugActions[2]( instring, tokensStart, self, err )
if self.failAction:
self.failAction( instring, tokensStart, self, err )
raise
else:
if callPreParse:
preloc = self.preParse( instring, loc )
else:
preloc = loc
tokensStart = loc
if self.mayIndexError or loc >= len(instring):
try:
loc,tokens = self.parseImpl( instring, preloc, doActions )
except IndexError:
raise ParseException( instring, len(instring), self.errmsg, self )
else:
loc,tokens = self.parseImpl( instring, preloc, doActions )
tokens = self.postParse( instring, loc, tokens )
 
retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
if self.parseAction and doActions:
if debugging:
try:
for fn in self.parseAction:
tokens = fn( instring, tokensStart, retTokens )
if tokens is not None:
retTokens = ParseResults( tokens,
self.resultsName,
asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
modal=self.modalResults )
except ParseException, err:
#~ print "Exception raised in user parse action:", err
if (self.debugActions[2] ):
self.debugActions[2]( instring, tokensStart, self, err )
raise
else:
for fn in self.parseAction:
tokens = fn( instring, tokensStart, retTokens )
if tokens is not None:
retTokens = ParseResults( tokens,
self.resultsName,
asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
modal=self.modalResults )
 
if debugging:
#~ print "Matched",self,"->",retTokens.asList()
if (self.debugActions[1] ):
self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
 
return loc, retTokens
 
def tryParse( self, instring, loc ):
return self._parse( instring, loc, doActions=False )[0]
# this method gets repeatedly called during backtracking with the same arguments -
# we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
if doActions and self.parseAction:
return self._parseNoCache( instring, loc, doActions, callPreParse )
lookup = (self,instring,loc,callPreParse)
if lookup in ParserElement._exprArgCache:
value = ParserElement._exprArgCache[ lookup ]
if isinstance(value,Exception):
if isinstance(value,ParseBaseException):
value.loc = loc
raise value
return value
else:
try:
ParserElement._exprArgCache[ lookup ] = \
value = self._parseNoCache( instring, loc, doActions, callPreParse )
return value
except ParseBaseException, pe:
ParserElement._exprArgCache[ lookup ] = pe
raise
 
_parse = _parseNoCache
 
# argument cache for optimizing repeated calls when backtracking through recursive expressions
_exprArgCache = {}
def resetCache():
ParserElement._exprArgCache.clear()
resetCache = staticmethod(resetCache)
_packratEnabled = False
def enablePackrat():
"""Enables "packrat" parsing, which adds memoizing to the parsing logic.
Repeated parse attempts at the same string location (which happens
often in many complex grammars) can immediately return a cached value,
instead of re-executing parsing/validating code. Memoizing is done of
both valid results and parsing exceptions.
This speedup may break existing programs that use parse actions that
have side-effects. For this reason, packrat parsing is disabled when
you first import pyparsing. To activate the packrat feature, your
program must call the class method ParserElement.enablePackrat(). If
your program uses psyco to "compile as you go", you must call
enablePackrat before calling psyco.full(). If you do not do this,
Python will crash. For best results, call enablePackrat() immediately
after importing pyparsing.
"""
if not ParserElement._packratEnabled:
ParserElement._packratEnabled = True
ParserElement._parse = ParserElement._parseCache
enablePackrat = staticmethod(enablePackrat)
 
def parseString( self, instring ):
"""Execute the parse expression with the given string.
This is the main interface to the client code, once the complete
expression has been built.
"""
ParserElement.resetCache()
if not self.streamlined:
self.streamline()
#~ self.saveAsList = True
for e in self.ignoreExprs:
e.streamline()
if self.keepTabs:
loc, tokens = self._parse( instring, 0 )
else:
loc, tokens = self._parse( instring.expandtabs(), 0 )
return tokens
 
def scanString( self, instring, maxMatches=sys.maxint ):
"""Scan the input string for expression matches. Each match will return the
matching tokens, start location, and end location. May be called with optional
maxMatches argument, to clip scanning after 'n' matches are found."""
if not self.streamlined:
self.streamline()
for e in self.ignoreExprs:
e.streamline()
if not self.keepTabs:
instring = instring.expandtabs()
instrlen = len(instring)
loc = 0
preparseFn = self.preParse
parseFn = self._parse
ParserElement.resetCache()
matches = 0
while loc <= instrlen and matches < maxMatches:
try:
preloc = preparseFn( instring, loc )
nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
except ParseException:
loc = preloc+1
else:
matches += 1
yield tokens, preloc, nextLoc
loc = nextLoc
def transformString( self, instring ):
"""Extension to scanString, to modify matching text with modified tokens that may
be returned from a parse action. To use transformString, define a grammar and
attach a parse action to it that modifies the returned token list.
Invoking transformString() on a target string will then scan for matches,
and replace the matched text patterns according to the logic in the parse
action. transformString() returns the resulting transformed string."""
out = []
lastE = 0
# force preservation of <TAB>s, to minimize unwanted transformation of string, and to
# keep string locs straight between transformString and scanString
self.keepTabs = True
for t,s,e in self.scanString( instring ):
out.append( instring[lastE:s] )
if t:
if isinstance(t,ParseResults):
out += t.asList()
elif isinstance(t,list):
out += t
else:
out.append(t)
lastE = e
out.append(instring[lastE:])
return "".join(out)
 
def searchString( self, instring, maxMatches=sys.maxint ):
"""Another extension to scanString, simplifying the access to the tokens found
to match the given parse expression. May be called with optional
maxMatches argument, to clip searching after 'n' matches are found.
"""
return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
def __add__(self, other ):
"""Implementation of + operator - returns And"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return And( [ self, other ] )
 
def __radd__(self, other ):
"""Implementation of += operator"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return other + self
 
def __or__(self, other ):
"""Implementation of | operator - returns MatchFirst"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return MatchFirst( [ self, other ] )
 
def __ror__(self, other ):
"""Implementation of |= operator"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return other | self
 
def __xor__(self, other ):
"""Implementation of ^ operator - returns Or"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return Or( [ self, other ] )
 
def __rxor__(self, other ):
"""Implementation of ^= operator"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return other ^ self
 
def __and__(self, other ):
"""Implementation of & operator - returns Each"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return Each( [ self, other ] )
 
def __rand__(self, other ):
"""Implementation of right-& operator"""
if isinstance( other, basestring ):
other = Literal( other )
if not isinstance( other, ParserElement ):
warnings.warn("Cannot add element of type %s to ParserElement" % type(other),
SyntaxWarning, stacklevel=2)
return other & self
 
def __invert__( self ):
"""Implementation of ~ operator - returns NotAny"""
return NotAny( self )
 
def suppress( self ):
"""Suppresses the output of this ParserElement; useful to keep punctuation from
cluttering up returned output.
"""
return Suppress( self )
 
def leaveWhitespace( self ):
"""Disables the skipping of whitespace before matching the characters in the
ParserElement's defined pattern. This is normally only used internally by
the pyparsing module, but may be needed in some whitespace-sensitive grammars.
"""
self.skipWhitespace = False
return self
 
def setWhitespaceChars( self, chars ):
"""Overrides the default whitespace chars
"""
self.skipWhitespace = True
self.whiteChars = chars
self.copyDefaultWhiteChars = False
return self
def parseWithTabs( self ):
"""Overrides default behavior to expand <TAB>s to spaces before parsing the input string.
Must be called before parseString when the input grammar contains elements that
match <TAB> characters."""
self.keepTabs = True
return self
def ignore( self, other ):
"""Define expression to be ignored (e.g., comments) while doing pattern
matching; may be called repeatedly, to define multiple comment or other
ignorable patterns.
"""
if isinstance( other, Suppress ):
if other not in self.ignoreExprs:
self.ignoreExprs.append( other )
else:
self.ignoreExprs.append( Suppress( other ) )
return self
 
def setDebugActions( self, startAction, successAction, exceptionAction ):
"""Enable display of debugging messages while doing pattern matching."""
self.debugActions = (startAction or _defaultStartDebugAction,
successAction or _defaultSuccessDebugAction,
exceptionAction or _defaultExceptionDebugAction)
self.debug = True
return self
 
def setDebug( self, flag=True ):
"""Enable display of debugging messages while doing pattern matching."""
if flag:
self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
else:
self.debug = False
return self
 
def __str__( self ):
return self.name
 
def __repr__( self ):
return _ustr(self)
def streamline( self ):
self.streamlined = True
self.strRepr = None
return self
def checkRecursion( self, parseElementList ):
pass
def validate( self, validateTrace=[] ):
"""Check defined expressions for valid structure, check for infinite recursive definitions."""
self.checkRecursion( [] )
 
def parseFile( self, file_or_filename ):
"""Execute the parse expression on the given file or filename.
If a filename is specified (instead of a file object),
the entire file is opened, read, and closed before parsing.
"""
try:
file_contents = file_or_filename.read()
except AttributeError:
f = open(file_or_filename, "rb")
file_contents = f.read()
f.close()
return self.parseString(file_contents)
 
 
class Token(ParserElement):
"""Abstract ParserElement subclass, for defining atomic matching patterns."""
def __init__( self ):
super(Token,self).__init__( savelist=False )
self.myException = ParseException("",0,"",self)
 
def setName(self, name):
s = super(Token,self).setName(name)
self.errmsg = "Expected " + self.name
s.myException.msg = self.errmsg
return s
 
 
class Empty(Token):
"""An empty token, will always match."""
def __init__( self ):
super(Empty,self).__init__()
self.name = "Empty"
self.mayReturnEmpty = True
self.mayIndexError = False
 
 
class NoMatch(Token):
"""A token that will never match."""
def __init__( self ):
super(NoMatch,self).__init__()
self.name = "NoMatch"
self.mayReturnEmpty = True
self.mayIndexError = False
self.errmsg = "Unmatchable token"
self.myException.msg = self.errmsg
def parseImpl( self, instring, loc, doActions=True ):
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
 
class Literal(Token):
"""Token to exactly match a specified string."""
def __init__( self, matchString ):
super(Literal,self).__init__()
self.match = matchString
self.matchLen = len(matchString)
try:
self.firstMatchChar = matchString[0]
except IndexError:
warnings.warn("null string passed to Literal; use Empty() instead",
SyntaxWarning, stacklevel=2)
self.__class__ = Empty
self.name = '"%s"' % self.match
self.errmsg = "Expected " + self.name
self.mayReturnEmpty = False
self.myException.msg = self.errmsg
self.mayIndexError = False
 
# Performance tuning: this routine gets called a *lot*
# if this is a single character match string and the first character matches,
# short-circuit as quickly as possible, and avoid calling startswith
#~ @profile
def parseImpl( self, instring, loc, doActions=True ):
if (instring[loc] == self.firstMatchChar and
(self.matchLen==1 or instring.startswith(self.match,loc)) ):
return loc+self.matchLen, self.match
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
class Keyword(Token):
"""Token to exactly match a specified string as a keyword, that is, it must be
immediately followed by a non-keyword character. Compare with Literal::
Literal("if") will match the leading 'if' in 'ifAndOnlyIf'.
Keyword("if") will not; it will only match the leading 'if in 'if x=1', or 'if(y==2)'
Accepts two optional constructor arguments in addition to the keyword string:
identChars is a string of characters that would be valid identifier characters,
defaulting to all alphanumerics + "_" and "$"; caseless allows case-insensitive
matching, default is False.
"""
DEFAULT_KEYWORD_CHARS = alphanums+"_$"
def __init__( self, matchString, identChars=DEFAULT_KEYWORD_CHARS, caseless=False ):
super(Keyword,self).__init__()
self.match = matchString
self.matchLen = len(matchString)
try:
self.firstMatchChar = matchString[0]
except IndexError:
warnings.warn("null string passed to Keyword; use Empty() instead",
SyntaxWarning, stacklevel=2)
self.name = '"%s"' % self.match
self.errmsg = "Expected " + self.name
self.mayReturnEmpty = False
self.myException.msg = self.errmsg
self.mayIndexError = False
self.caseless = caseless
if caseless:
self.caselessmatch = matchString.upper()
identChars = identChars.upper()
self.identChars = _str2dict(identChars)
 
def parseImpl( self, instring, loc, doActions=True ):
if self.caseless:
if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
(loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
(loc == 0 or instring[loc-1].upper() not in self.identChars) ):
return loc+self.matchLen, self.match
else:
if (instring[loc] == self.firstMatchChar and
(self.matchLen==1 or instring.startswith(self.match,loc)) and
(loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
(loc == 0 or instring[loc-1] not in self.identChars) ):
return loc+self.matchLen, self.match
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
def copy(self):
c = super(Keyword,self).copy()
c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
return c
def setDefaultKeywordChars( chars ):
"""Overrides the default Keyword chars
"""
Keyword.DEFAULT_KEYWORD_CHARS = chars
setDefaultKeywordChars = staticmethod(setDefaultKeywordChars)
 
 
class CaselessLiteral(Literal):
"""Token to match a specified string, ignoring case of letters.
Note: the matched results will always be in the case of the given
match string, NOT the case of the input text.
"""
def __init__( self, matchString ):
super(CaselessLiteral,self).__init__( matchString.upper() )
# Preserve the defining literal.
self.returnString = matchString
self.name = "'%s'" % self.returnString
self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg
 
def parseImpl( self, instring, loc, doActions=True ):
if instring[ loc:loc+self.matchLen ].upper() == self.match:
return loc+self.matchLen, self.returnString
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
class CaselessKeyword(Keyword):
def __init__( self, matchString, identChars=Keyword.DEFAULT_KEYWORD_CHARS ):
super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
 
def parseImpl( self, instring, loc, doActions=True ):
if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
(loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
return loc+self.matchLen, self.match
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
class Word(Token):
"""Token for matching words composed of allowed character sets.
Defined with string containing all allowed initial characters,
an optional string containing allowed body characters (if omitted,
defaults to the initial character set), and an optional minimum,
maximum, and/or exact length.
"""
def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0 ):
super(Word,self).__init__()
self.initCharsOrig = initChars
self.initChars = _str2dict(initChars)
if bodyChars :
self.bodyCharsOrig = bodyChars
self.bodyChars = _str2dict(bodyChars)
else:
self.bodyCharsOrig = initChars
self.bodyChars = _str2dict(initChars)
self.maxSpecified = max > 0
 
self.minLen = min
 
if max > 0:
self.maxLen = max
else:
self.maxLen = sys.maxint
 
if exact > 0:
self.maxLen = exact
self.minLen = exact
 
self.name = _ustr(self)
self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg
self.mayIndexError = False
if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
if self.bodyCharsOrig == self.initCharsOrig:
self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
elif len(self.bodyCharsOrig) == 1:
self.reString = "%s[%s]*" % \
(re.escape(self.initCharsOrig),
_escapeRegexRangeChars(self.bodyCharsOrig),)
else:
self.reString = "[%s][%s]*" % \
(_escapeRegexRangeChars(self.initCharsOrig),
_escapeRegexRangeChars(self.bodyCharsOrig),)
try:
self.re = re.compile( self.reString )
except:
self.re = None
def parseImpl( self, instring, loc, doActions=True ):
if self.re:
result = self.re.match(instring,loc)
if not result:
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
loc = result.end()
return loc,result.group()
if not(instring[ loc ] in self.initChars):
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
start = loc
loc += 1
instrlen = len(instring)
bodychars = self.bodyChars
maxloc = start + self.maxLen
maxloc = min( maxloc, instrlen )
while loc < maxloc and instring[loc] in bodychars:
loc += 1
throwException = False
if loc - start < self.minLen:
throwException = True
if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
throwException = True
 
if throwException:
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
return loc, instring[start:loc]
 
def __str__( self ):
try:
return super(Word,self).__str__()
except:
pass
 
if self.strRepr is None:
def charsAsStr(s):
if len(s)>4:
return s[:4]+"..."
else:
return s
if ( self.initCharsOrig != self.bodyCharsOrig ):
self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
else:
self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
 
return self.strRepr
 
 
class Regex(Token):
"""Token for matching strings that match a given regular expression.
Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
"""
def __init__( self, pattern, flags=0):
"""The parameters pattern and flags are passed to the re.compile() function as-is. See the Python re module for an explanation of the acceptable patterns and flags."""
super(Regex,self).__init__()
if len(pattern) == 0:
warnings.warn("null string passed to Regex; use Empty() instead",
SyntaxWarning, stacklevel=2)
self.pattern = pattern
self.flags = flags
try:
self.re = re.compile(self.pattern, self.flags)
self.reString = self.pattern
except sre_constants.error,e:
warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
SyntaxWarning, stacklevel=2)
raise
 
self.name = _ustr(self)
self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg
self.mayIndexError = False
self.mayReturnEmpty = True
def parseImpl( self, instring, loc, doActions=True ):
result = self.re.match(instring,loc)
if not result:
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
loc = result.end()
d = result.groupdict()
ret = ParseResults(result.group())
if d:
for k in d.keys():
ret[k] = d[k]
return loc,ret
def __str__( self ):
try:
return super(Regex,self).__str__()
except:
pass
if self.strRepr is None:
self.strRepr = "Re:(%s)" % repr(self.pattern)
return self.strRepr
 
 
class QuotedString(Token):
"""Token for matching strings that are delimited by quoting characters.
"""
def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None):
"""
Defined with the following parameters:
- quoteChar - string of one or more characters defining the quote delimiting string
- escChar - character to escape quotes, typically backslash (default=None)
- escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None)
- multiline - boolean indicating whether quotes can span multiple lines (default=False)
- unquoteResults - boolean indicating whether the matched text should be unquoted (default=True)
- endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar)
"""
super(QuotedString,self).__init__()
# remove white space from quote chars - wont work anyway
quoteChar = quoteChar.strip()
if len(quoteChar) == 0:
warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
raise SyntaxError()
if endQuoteChar is None:
endQuoteChar = quoteChar
else:
endQuoteChar = endQuoteChar.strip()
if len(endQuoteChar) == 0:
warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
raise SyntaxError()
self.quoteChar = quoteChar
self.quoteCharLen = len(quoteChar)
self.firstQuoteChar = quoteChar[0]
self.endQuoteChar = endQuoteChar
self.endQuoteCharLen = len(endQuoteChar)
self.escChar = escChar
self.escQuote = escQuote
self.unquoteResults = unquoteResults
if multiline:
self.flags = re.MULTILINE | re.DOTALL
self.pattern = r'%s(?:[^%s%s]' % \
( re.escape(self.quoteChar),
_escapeRegexRangeChars(self.endQuoteChar[0]),
(escChar is not None and _escapeRegexRangeChars(escChar) or '') )
else:
self.flags = 0
self.pattern = r'%s(?:[^%s\n\r%s]' % \
( re.escape(self.quoteChar),
_escapeRegexRangeChars(self.endQuoteChar[0]),
(escChar is not None and _escapeRegexRangeChars(escChar) or '') )
if len(self.endQuoteChar) > 1:
self.pattern += (
'|(?:' + ')|(?:'.join(["%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
_escapeRegexRangeChars(self.endQuoteChar[i]))
for i in range(len(self.endQuoteChar)-1,0,-1)]) + ')'
)
if escQuote:
self.pattern += (r'|(?:%s)' % re.escape(escQuote))
if escChar:
self.pattern += (r'|(?:%s.)' % re.escape(escChar))
self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
try:
self.re = re.compile(self.pattern, self.flags)
self.reString = self.pattern
except sre_constants.error,e:
warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
SyntaxWarning, stacklevel=2)
raise
 
self.name = _ustr(self)
self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg
self.mayIndexError = False
self.mayReturnEmpty = True
def parseImpl( self, instring, loc, doActions=True ):
result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
if not result:
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
loc = result.end()
ret = result.group()
print ret
if self.unquoteResults:
# strip off quotes
ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
if isinstance(ret,basestring):
# replace escaped characters
if self.escChar:
ret = re.sub(self.escCharReplacePattern,"\g<1>",ret)
 
# replace escaped quotes
if self.escQuote:
ret = ret.replace(self.escQuote, self.endQuoteChar)
 
return loc, ret
def __str__( self ):
try:
return super(QuotedString,self).__str__()
except:
pass
if self.strRepr is None:
self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
return self.strRepr
 
 
class CharsNotIn(Token):
"""Token for matching words composed of characters *not* in a given set.
Defined with string containing all disallowed characters, and an optional
minimum, maximum, and/or exact length.
"""
def __init__( self, notChars, min=1, max=0, exact=0 ):
super(CharsNotIn,self).__init__()
self.skipWhitespace = False
self.notChars = notChars
self.minLen = min
 
if max > 0:
self.maxLen = max
else:
self.maxLen = sys.maxint
 
if exact > 0:
self.maxLen = exact
self.minLen = exact
self.name = _ustr(self)
self.errmsg = "Expected " + self.name
self.mayReturnEmpty = ( self.minLen == 0 )
self.myException.msg = self.errmsg
self.mayIndexError = False
 
def parseImpl( self, instring, loc, doActions=True ):
if instring[loc] in self.notChars:
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
start = loc
loc += 1
notchars = self.notChars
maxlen = min( start+self.maxLen, len(instring) )
while loc < maxlen and \
(instring[loc] not in notchars):
loc += 1
 
if loc - start < self.minLen:
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
return loc, instring[start:loc]
 
def __str__( self ):
try:
return super(CharsNotIn, self).__str__()
except:
pass
 
if self.strRepr is None:
if len(self.notChars) > 4:
self.strRepr = "!W:(%s...)" % self.notChars[:4]
else:
self.strRepr = "!W:(%s)" % self.notChars
return self.strRepr
 
class White(Token):
"""Special matching class for matching whitespace. Normally, whitespace is ignored
by pyparsing grammars. This class is included when some whitespace structures
are significant. Define with a string containing the whitespace characters to be
matched; default is " \\t\\n". Also takes optional min, max, and exact arguments,
as defined for the Word class."""
whiteStrs = {
" " : "<SPC>",
"\t": "<TAB>",
"\n": "<LF>",
"\r": "<CR>",
"\f": "<FF>",
}
def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
super(White,self).__init__()
self.matchWhite = ws
self.setWhitespaceChars( "".join([c for c in self.whiteChars if c not in self.matchWhite]) )
#~ self.leaveWhitespace()
self.name = ("".join([White.whiteStrs[c] for c in self.matchWhite]))
self.mayReturnEmpty = True
self.errmsg = "Expected " + self.name
self.myException.msg = self.errmsg
 
self.minLen = min
 
if max > 0:
self.maxLen = max
else:
self.maxLen = sys.maxint
 
if exact > 0:
self.maxLen = exact
self.minLen = exact
def parseImpl( self, instring, loc, doActions=True ):
if not(instring[ loc ] in self.matchWhite):
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
start = loc
loc += 1
maxloc = start + self.maxLen
maxloc = min( maxloc, len(instring) )
while loc < maxloc and instring[loc] in self.matchWhite:
loc += 1
 
if loc - start < self.minLen:
#~ raise ParseException( instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
return loc, instring[start:loc]
 
 
class PositionToken(Token):
def __init__( self ):
super(PositionToken,self).__init__()
self.name=self.__class__.__name__
self.mayReturnEmpty = True
self.mayIndexError = False
 
class GoToColumn(PositionToken):
"""Token to advance to a specific column of input text; useful for tabular report scraping."""
def __init__( self, colno ):
super(GoToColumn,self).__init__()
self.col = colno
 
def preParse( self, instring, loc ):
if col(loc,instring) != self.col:
instrlen = len(instring)
if self.ignoreExprs:
loc = self.skipIgnorables( instring, loc )
while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
loc += 1
return loc
 
def parseImpl( self, instring, loc, doActions=True ):
thiscol = col( loc, instring )
if thiscol > self.col:
raise ParseException( instring, loc, "Text not in expected column", self )
newloc = loc + self.col - thiscol
ret = instring[ loc: newloc ]
return newloc, ret
 
class LineStart(PositionToken):
"""Matches if current position is at the beginning of a line within the parse string"""
def __init__( self ):
super(LineStart,self).__init__()
self.setWhitespaceChars( " \t" )
self.errmsg = "Expected start of line"
self.myException.msg = self.errmsg
 
def preParse( self, instring, loc ):
preloc = super(LineStart,self).preParse(instring,loc)
if instring[preloc] == "\n":
loc += 1
return loc
 
def parseImpl( self, instring, loc, doActions=True ):
if not( loc==0 or ( loc<len(instring) and instring[loc-1] == "\n" ) ): #col(loc, instring) != 1:
#~ raise ParseException( instring, loc, "Expected start of line" )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
return loc, []
 
class LineEnd(PositionToken):
"""Matches if current position is at the end of a line within the parse string"""
def __init__( self ):
super(LineEnd,self).__init__()
self.setWhitespaceChars( " \t" )
self.errmsg = "Expected end of line"
self.myException.msg = self.errmsg
def parseImpl( self, instring, loc, doActions=True ):
if loc<len(instring):
if instring[loc] == "\n":
return loc+1, "\n"
else:
#~ raise ParseException( instring, loc, "Expected end of line" )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
elif loc == len(instring):
return loc+1, []
else:
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
class StringStart(PositionToken):
"""Matches if current position is at the beginning of the parse string"""
def __init__( self ):
super(StringStart,self).__init__()
self.errmsg = "Expected start of text"
self.myException.msg = self.errmsg
def parseImpl( self, instring, loc, doActions=True ):
if loc != 0:
# see if entire string up to here is just whitespace and ignoreables
if loc != self.preParse( instring, 0 ):
#~ raise ParseException( instring, loc, "Expected start of text" )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
return loc, []
 
class StringEnd(PositionToken):
"""Matches if current position is at the end of the parse string"""
def __init__( self ):
super(StringEnd,self).__init__()
self.errmsg = "Expected end of text"
self.myException.msg = self.errmsg
def parseImpl( self, instring, loc, doActions=True ):
if loc < len(instring):
#~ raise ParseException( instring, loc, "Expected end of text" )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
elif loc == len(instring):
return loc+1, []
else:
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
 
class ParseExpression(ParserElement):
"""Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
def __init__( self, exprs, savelist = False ):
super(ParseExpression,self).__init__(savelist)
if isinstance( exprs, list ):
self.exprs = exprs
elif isinstance( exprs, basestring ):
self.exprs = [ Literal( exprs ) ]
else:
self.exprs = [ exprs ]
 
def __getitem__( self, i ):
return self.exprs[i]
 
def append( self, other ):
self.exprs.append( other )
self.strRepr = None
return self
 
def leaveWhitespace( self ):
"""Extends leaveWhitespace defined in base class, and also invokes leaveWhitespace on
all contained expressions."""
self.skipWhitespace = False
self.exprs = [ e.copy() for e in self.exprs ]
for e in self.exprs:
e.leaveWhitespace()
return self
 
def ignore( self, other ):
if isinstance( other, Suppress ):
if other not in self.ignoreExprs:
super( ParseExpression, self).ignore( other )
for e in self.exprs:
e.ignore( self.ignoreExprs[-1] )
else:
super( ParseExpression, self).ignore( other )
for e in self.exprs:
e.ignore( self.ignoreExprs[-1] )
return self
 
def __str__( self ):
try:
return super(ParseExpression,self).__str__()
except:
pass
if self.strRepr is None:
self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.exprs) )
return self.strRepr
 
def streamline( self ):
super(ParseExpression,self).streamline()
 
for e in self.exprs:
e.streamline()
 
# collapse nested And's of the form And( And( And( a,b), c), d) to And( a,b,c,d )
# but only if there are no parse actions or resultsNames on the nested And's
# (likewise for Or's and MatchFirst's)
if ( len(self.exprs) == 2 ):
other = self.exprs[0]
if ( isinstance( other, self.__class__ ) and
not(other.parseAction) and
other.resultsName is None and
not other.debug ):
self.exprs = other.exprs[:] + [ self.exprs[1] ]
self.strRepr = None
self.mayReturnEmpty |= other.mayReturnEmpty
self.mayIndexError |= other.mayIndexError
 
other = self.exprs[-1]
if ( isinstance( other, self.__class__ ) and
not(other.parseAction) and
other.resultsName is None and
not other.debug ):
self.exprs = self.exprs[:-1] + other.exprs[:]
self.strRepr = None
self.mayReturnEmpty |= other.mayReturnEmpty
self.mayIndexError |= other.mayIndexError
 
return self
 
def setResultsName( self, name, listAllMatches=False ):
ret = super(ParseExpression,self).setResultsName(name,listAllMatches)
return ret
def validate( self, validateTrace=[] ):
tmp = validateTrace[:]+[self]
for e in self.exprs:
e.validate(tmp)
self.checkRecursion( [] )
 
class And(ParseExpression):
"""Requires all given ParseExpressions to be found in the given order.
Expressions may be separated by whitespace.
May be constructed using the '+' operator.
"""
def __init__( self, exprs, savelist = True ):
super(And,self).__init__(exprs, savelist)
self.mayReturnEmpty = True
for e in self.exprs:
if not e.mayReturnEmpty:
self.mayReturnEmpty = False
break
self.setWhitespaceChars( exprs[0].whiteChars )
self.skipWhitespace = exprs[0].skipWhitespace
 
def parseImpl( self, instring, loc, doActions=True ):
loc, resultlist = self.exprs[0]._parse( instring, loc, doActions )
for e in self.exprs[1:]:
loc, exprtokens = e._parse( instring, loc, doActions )
if exprtokens or exprtokens.keys():
resultlist += exprtokens
return loc, resultlist
 
def __iadd__(self, other ):
if isinstance( other, basestring ):
other = Literal( other )
return self.append( other ) #And( [ self, other ] )
def checkRecursion( self, parseElementList ):
subRecCheckList = parseElementList[:] + [ self ]
for e in self.exprs:
e.checkRecursion( subRecCheckList )
if not e.mayReturnEmpty:
break
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "{" + " ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
return self.strRepr
 
class Or(ParseExpression):
"""Requires that at least one ParseExpression is found.
If two expressions match, the expression that matches the longest string will be used.
May be constructed using the '^' operator.
"""
def __init__( self, exprs, savelist = False ):
super(Or,self).__init__(exprs, savelist)
self.mayReturnEmpty = False
for e in self.exprs:
if e.mayReturnEmpty:
self.mayReturnEmpty = True
break
def parseImpl( self, instring, loc, doActions=True ):
maxExcLoc = -1
maxMatchLoc = -1
for e in self.exprs:
try:
loc2 = e.tryParse( instring, loc )
except ParseException, err:
if err.loc > maxExcLoc:
maxException = err
maxExcLoc = err.loc
except IndexError, err:
if len(instring) > maxExcLoc:
maxException = ParseException(instring,len(instring),e.errmsg,self)
maxExcLoc = len(instring)
else:
if loc2 > maxMatchLoc:
maxMatchLoc = loc2
maxMatchExp = e
if maxMatchLoc < 0:
if self.exprs:
raise maxException
else:
raise ParseException(instring, loc, "no defined alternatives to match", self)
 
return maxMatchExp._parse( instring, loc, doActions )
 
def __ixor__(self, other ):
if isinstance( other, basestring ):
other = Literal( other )
return self.append( other ) #Or( [ self, other ] )
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "{" + " ^ ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
return self.strRepr
def checkRecursion( self, parseElementList ):
subRecCheckList = parseElementList[:] + [ self ]
for e in self.exprs:
e.checkRecursion( subRecCheckList )
 
 
class MatchFirst(ParseExpression):
"""Requires that at least one ParseExpression is found.
If two expressions match, the first one listed is the one that will match.
May be constructed using the '|' operator.
"""
def __init__( self, exprs, savelist = False ):
super(MatchFirst,self).__init__(exprs, savelist)
if exprs:
self.mayReturnEmpty = False
for e in self.exprs:
if e.mayReturnEmpty:
self.mayReturnEmpty = True
break
else:
self.mayReturnEmpty = True
def parseImpl( self, instring, loc, doActions=True ):
maxExcLoc = -1
for e in self.exprs:
try:
ret = e._parse( instring, loc, doActions )
return ret
except ParseException, err:
if err.loc > maxExcLoc:
maxException = err
maxExcLoc = err.loc
except IndexError, err:
if len(instring) > maxExcLoc:
maxException = ParseException(instring,len(instring),e.errmsg,self)
maxExcLoc = len(instring)
 
# only got here if no expression matched, raise exception for match that made it the furthest
else:
if self.exprs:
raise maxException
else:
raise ParseException(instring, loc, "no defined alternatives to match", self)
 
def __ior__(self, other ):
if isinstance( other, basestring ):
other = Literal( other )
return self.append( other ) #MatchFirst( [ self, other ] )
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "{" + " | ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
return self.strRepr
def checkRecursion( self, parseElementList ):
subRecCheckList = parseElementList[:] + [ self ]
for e in self.exprs:
e.checkRecursion( subRecCheckList )
 
class Each(ParseExpression):
"""Requires all given ParseExpressions to be found, but in any order.
Expressions may be separated by whitespace.
May be constructed using the '&' operator.
"""
def __init__( self, exprs, savelist = True ):
super(Each,self).__init__(exprs, savelist)
self.mayReturnEmpty = True
for e in self.exprs:
if not e.mayReturnEmpty:
self.mayReturnEmpty = False
break
self.skipWhitespace = True
self.optionals = [ e.expr for e in exprs if isinstance(e,Optional) ]
self.multioptionals = [ e.expr for e in exprs if isinstance(e,ZeroOrMore) ]
self.multirequired = [ e.expr for e in exprs if isinstance(e,OneOrMore) ]
self.required = [ e for e in exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
self.required += self.multirequired
 
def parseImpl( self, instring, loc, doActions=True ):
tmpLoc = loc
tmpReqd = self.required[:]
tmpOpt = self.optionals[:]
matchOrder = []
 
keepMatching = True
while keepMatching:
tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
failed = []
for e in tmpExprs:
try:
tmpLoc = e.tryParse( instring, tmpLoc )
except ParseException:
failed.append(e)
else:
matchOrder.append(e)
if e in tmpReqd:
tmpReqd.remove(e)
elif e in tmpOpt:
tmpOpt.remove(e)
if len(failed) == len(tmpExprs):
keepMatching = False
if tmpReqd:
missing = ", ".join( [ _ustr(e) for e in tmpReqd ] )
raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
 
resultlist = []
for e in matchOrder:
loc,results = e._parse(instring,loc,doActions)
resultlist.append(results)
finalResults = ParseResults([])
for r in resultlist:
dups = {}
for k in r.keys():
if k in finalResults.keys():
tmp = ParseResults(finalResults[k])
tmp += ParseResults(r[k])
dups[k] = tmp
finalResults += ParseResults(r)
for k,v in dups.items():
finalResults[k] = v
return loc, finalResults
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "{" + " & ".join( [ _ustr(e) for e in self.exprs ] ) + "}"
return self.strRepr
def checkRecursion( self, parseElementList ):
subRecCheckList = parseElementList[:] + [ self ]
for e in self.exprs:
e.checkRecursion( subRecCheckList )
 
 
class ParseElementEnhance(ParserElement):
"""Abstract subclass of ParserElement, for combining and post-processing parsed tokens."""
def __init__( self, expr, savelist=False ):
super(ParseElementEnhance,self).__init__(savelist)
if isinstance( expr, basestring ):
expr = Literal(expr)
self.expr = expr
self.strRepr = None
if expr is not None:
self.mayIndexError = expr.mayIndexError
self.setWhitespaceChars( expr.whiteChars )
self.skipWhitespace = expr.skipWhitespace
self.saveAsList = expr.saveAsList
def parseImpl( self, instring, loc, doActions=True ):
if self.expr is not None:
return self.expr._parse( instring, loc, doActions )
else:
raise ParseException("",loc,self.errmsg,self)
def leaveWhitespace( self ):
self.skipWhitespace = False
self.expr = self.expr.copy()
if self.expr is not None:
self.expr.leaveWhitespace()
return self
 
def ignore( self, other ):
if isinstance( other, Suppress ):
if other not in self.ignoreExprs:
super( ParseElementEnhance, self).ignore( other )
if self.expr is not None:
self.expr.ignore( self.ignoreExprs[-1] )
else:
super( ParseElementEnhance, self).ignore( other )
if self.expr is not None:
self.expr.ignore( self.ignoreExprs[-1] )
return self
 
def streamline( self ):
super(ParseElementEnhance,self).streamline()
if self.expr is not None:
self.expr.streamline()
return self
 
def checkRecursion( self, parseElementList ):
if self in parseElementList:
raise RecursiveGrammarException( parseElementList+[self] )
subRecCheckList = parseElementList[:] + [ self ]
if self.expr is not None:
self.expr.checkRecursion( subRecCheckList )
def validate( self, validateTrace=[] ):
tmp = validateTrace[:]+[self]
if self.expr is not None:
self.expr.validate(tmp)
self.checkRecursion( [] )
def __str__( self ):
try:
return super(ParseElementEnhance,self).__str__()
except:
pass
if self.strRepr is None and self.expr is not None:
self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
return self.strRepr
 
 
class FollowedBy(ParseElementEnhance):
"""Lookahead matching of the given parse expression. FollowedBy
does *not* advance the parsing position within the input string, it only
verifies that the specified parse expression matches at the current
position. FollowedBy always returns a null token list."""
def __init__( self, expr ):
super(FollowedBy,self).__init__(expr)
self.mayReturnEmpty = True
def parseImpl( self, instring, loc, doActions=True ):
self.expr.tryParse( instring, loc )
return loc, []
 
 
class NotAny(ParseElementEnhance):
"""Lookahead to disallow matching with the given parse expression. NotAny
does *not* advance the parsing position within the input string, it only
verifies that the specified parse expression does *not* match at the current
position. Also, NotAny does *not* skip over leading whitespace. NotAny
always returns a null token list. May be constructed using the '~' operator."""
def __init__( self, expr ):
super(NotAny,self).__init__(expr)
#~ self.leaveWhitespace()
self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
self.mayReturnEmpty = True
self.errmsg = "Found unwanted token, "+_ustr(self.expr)
self.myException = ParseException("",0,self.errmsg,self)
def parseImpl( self, instring, loc, doActions=True ):
try:
self.expr.tryParse( instring, loc )
except (ParseException,IndexError):
pass
else:
#~ raise ParseException(instring, loc, self.errmsg )
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
return loc, []
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "~{" + _ustr(self.expr) + "}"
return self.strRepr
 
 
class ZeroOrMore(ParseElementEnhance):
"""Optional repetition of zero or more of the given expression."""
def __init__( self, expr ):
super(ZeroOrMore,self).__init__(expr)
self.mayReturnEmpty = True
def parseImpl( self, instring, loc, doActions=True ):
tokens = []
try:
loc, tokens = self.expr._parse( instring, loc, doActions )
hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
while 1:
if hasIgnoreExprs:
preloc = self.skipIgnorables( instring, loc )
else:
preloc = loc
loc, tmptokens = self.expr._parse( instring, preloc, doActions )
if tmptokens or tmptokens.keys():
tokens += tmptokens
except (ParseException,IndexError):
pass
 
return loc, tokens
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "[" + _ustr(self.expr) + "]..."
return self.strRepr
def setResultsName( self, name, listAllMatches=False ):
ret = super(ZeroOrMore,self).setResultsName(name,listAllMatches)
ret.saveAsList = True
return ret
 
class OneOrMore(ParseElementEnhance):
"""Repetition of one or more of the given expression."""
def parseImpl( self, instring, loc, doActions=True ):
# must be at least one
loc, tokens = self.expr._parse( instring, loc, doActions )
try:
hasIgnoreExprs = ( len(self.ignoreExprs) > 0 )
while 1:
if hasIgnoreExprs:
preloc = self.skipIgnorables( instring, loc )
else:
preloc = loc
loc, tmptokens = self.expr._parse( instring, preloc, doActions )
if tmptokens or tmptokens.keys():
tokens += tmptokens
except (ParseException,IndexError):
pass
 
return loc, tokens
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "{" + _ustr(self.expr) + "}..."
return self.strRepr
def setResultsName( self, name, listAllMatches=False ):
ret = super(OneOrMore,self).setResultsName(name,listAllMatches)
ret.saveAsList = True
return ret
 
class _NullToken(object):
def __bool__(self):
return False
def __str__(self):
return ""
 
_optionalNotMatched = _NullToken()
class Optional(ParseElementEnhance):
"""Optional matching of the given expression.
A default return string can also be specified, if the optional expression
is not found.
"""
def __init__( self, exprs, default=_optionalNotMatched ):
super(Optional,self).__init__( exprs, savelist=False )
self.defaultValue = default
self.mayReturnEmpty = True
 
def parseImpl( self, instring, loc, doActions=True ):
try:
loc, tokens = self.expr._parse( instring, loc, doActions )
except (ParseException,IndexError):
if self.defaultValue is not _optionalNotMatched:
tokens = [ self.defaultValue ]
else:
tokens = []
return loc, tokens
 
def __str__( self ):
if hasattr(self,"name"):
return self.name
if self.strRepr is None:
self.strRepr = "[" + _ustr(self.expr) + "]"
return self.strRepr
 
 
class SkipTo(ParseElementEnhance):
"""Token for skipping over all undefined text until the matched expression is found.
If include is set to true, the matched expression is also consumed. The ignore
argument is used to define grammars (typically quoted strings and comments) that
might contain false matches.
"""
def __init__( self, other, include=False, ignore=None ):
super( SkipTo, self ).__init__( other )
if ignore is not None:
self.expr = self.expr.copy()
self.expr.ignore(ignore)
self.mayReturnEmpty = True
self.mayIndexError = False
self.includeMatch = include
self.asList = False
self.errmsg = "No match found for "+_ustr(self.expr)
self.myException = ParseException("",0,self.errmsg,self)
 
def parseImpl( self, instring, loc, doActions=True ):
startLoc = loc
instrlen = len(instring)
expr = self.expr
while loc <= instrlen:
try:
loc = expr.skipIgnorables( instring, loc )
expr._parse( instring, loc, doActions=False, callPreParse=False )
if self.includeMatch:
skipText = instring[startLoc:loc]
loc,mat = expr._parse(instring,loc)
if mat:
return loc, [ skipText, mat ]
else:
return loc, [ skipText ]
else:
return loc, [ instring[startLoc:loc] ]
except (ParseException,IndexError):
loc += 1
exc = self.myException
exc.loc = loc
exc.pstr = instring
raise exc
 
class Forward(ParseElementEnhance):
"""Forward declaration of an expression to be defined later -
used for recursive grammars, such as algebraic infix notation.
When the expression is known, it is assigned to the Forward variable using the '<<' operator.
Note: take care when assigning to Forward not to overlook precedence of operators.
Specifically, '|' has a lower precedence than '<<', so that::
fwdExpr << a | b | c
will actually be evaluated as::
(fwdExpr << a) | b | c
thereby leaving b and c out as parseable alternatives. It is recommended that you
explicitly group the values inserted into the Forward::
fwdExpr << (a | b | c)
"""
def __init__( self, other=None ):
super(Forward,self).__init__( other, savelist=False )
 
def __lshift__( self, other ):
if isinstance( other, basestring ):
other = Literal(other)
self.expr = other
self.mayReturnEmpty = other.mayReturnEmpty
self.strRepr = None
return self
 
def leaveWhitespace( self ):
self.skipWhitespace = False
return self
 
def streamline( self ):
if not self.streamlined:
self.streamlined = True
if self.expr is not None:
self.expr.streamline()
return self
 
def validate( self, validateTrace=[] ):
if self not in validateTrace:
tmp = validateTrace[:]+[self]
if self.expr is not None:
self.expr.validate(tmp)
self.checkRecursion([])
def __str__( self ):
if hasattr(self,"name"):
return self.name
 
self.__class__ = _ForwardNoRecurse
try:
if self.expr is not None:
retString = _ustr(self.expr)
else:
retString = "None"
finally:
self.__class__ = Forward
return "Forward: "+retString
def copy(self):
if self.expr is not None:
return super(Forward,self).copy()
else:
ret = Forward()
ret << self
return ret
 
class _ForwardNoRecurse(Forward):
def __str__( self ):
return "..."
class TokenConverter(ParseElementEnhance):
"""Abstract subclass of ParseExpression, for converting parsed results."""
def __init__( self, expr, savelist=False ):
super(TokenConverter,self).__init__( expr )#, savelist )
self.saveAsList = False
 
 
class Upcase(TokenConverter):
"""Converter to upper case all matching tokens."""
def __init__(self, *args):
super(Upcase,self).__init__(*args)
def postParse( self, instring, loc, tokenlist ):
return map( string.upper, tokenlist )
 
 
class Downcase(TokenConverter):
"""Converter to upper case all matching tokens."""
def __init__(self, *args):
super(Downcase,self).__init__(*args)
def postParse( self, instring, loc, tokenlist ):
return map( string.lower, tokenlist )
 
 
 
class Combine(TokenConverter):
"""Converter to concatenate all matching tokens to a single string.
By default, the matching patterns must also be contiguous in the input string;
this can be disabled by specifying 'adjacent=False' in the constructor.
"""
def __init__( self, expr, joinString="", adjacent=True ):
super(Combine,self).__init__( expr )
# suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
if adjacent:
self.leaveWhitespace()
self.adjacent = adjacent
self.skipWhitespace = True
self.joinString = joinString
 
def ignore( self, other ):
if self.adjacent:
ParserElement.ignore(self, other)
else:
super( Combine, self).ignore( other )
return self
 
def postParse( self, instring, loc, tokenlist ):
retToks = tokenlist.copy()
del retToks[:]
retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
 
if self.resultsName and len(retToks.keys())>0:
return [ retToks ]
else:
return retToks
 
class Group(TokenConverter):
"""Converter to return the matched tokens as a list - useful for returning tokens of ZeroOrMore and OneOrMore expressions."""
def __init__( self, expr ):
super(Group,self).__init__( expr )
self.saveAsList = True
 
def postParse( self, instring, loc, tokenlist ):
return [ tokenlist ]
class Dict(TokenConverter):
"""Converter to return a repetitive expression as a list, but also as a dictionary.
Each element can also be referenced using the first token in the expression as its key.
Useful for tabular report scraping when the first column can be used as a item key.
"""
def __init__( self, exprs ):
super(Dict,self).__init__( exprs )
self.saveAsList = True
 
def postParse( self, instring, loc, tokenlist ):
for i,tok in enumerate(tokenlist):
ikey = _ustr(tok[0]).strip()
if len(tok)==1:
tokenlist[ikey] = ("",i)
elif len(tok)==2 and not isinstance(tok[1],ParseResults):
tokenlist[ikey] = (tok[1],i)
else:
dictvalue = tok.copy() #ParseResults(i)
del dictvalue[0]
if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.keys()):
tokenlist[ikey] = (dictvalue,i)
else:
tokenlist[ikey] = (dictvalue[0],i)
 
if self.resultsName:
return [ tokenlist ]
else:
return tokenlist
 
 
class Suppress(TokenConverter):
"""Converter for ignoring the results of a parsed expression."""
def postParse( self, instring, loc, tokenlist ):
return []
def suppress( self ):
return self
 
 
class OnlyOnce(object):
"""Wrapper for parse actions, to ensure they are only called once."""
def __init__(self, methodCall):
self.callable = ParserElement.normalizeParseActionArgs(methodCall)
self.called = False
def __call__(self,s,l,t):
if not self.called:
results = self.callable(s,l,t)
self.called = True
return results
raise ParseException(s,l,"")
def reset():
self.called = False
 
def traceParseAction(f):
"""Decorator for debugging parse actions."""
f = ParserElement.normalizeParseActionArgs(f)
def z(*paArgs):
thisFunc = f.func_name
s,l,t = paArgs[-3:]
if len(paArgs)>3:
thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
sys.stderr.write( ">>entering %s(line: '%s', %d, %s)\n" % (thisFunc,line(l,s),l,t) )
try:
ret = f(*paArgs)
except Exception, exc:
sys.stderr.write( "<<leaving %s (exception: %s)\n" % (thisFunc,exc) )
raise
sys.stderr.write( "<<leaving %s (ret: %s)\n" % (thisFunc,ret) )
return ret
return z
#
# global helpers
#
def delimitedList( expr, delim=",", combine=False ):
"""Helper to define a delimited list of expressions - the delimiter defaults to ','.
By default, the list elements and delimiters can have intervening whitespace, and
comments, but this can be overridden by passing 'combine=True' in the constructor.
If combine is set to True, the matching tokens are returned as a single token
string, with the delimiters included; otherwise, the matching tokens are returned
as a list of tokens, with the delimiters suppressed.
"""
dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
if combine:
return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
else:
return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
 
def countedArray( expr ):
"""Helper to define a counted list of expressions.
This helper defines a pattern of the form::
integer expr expr expr...
where the leading integer tells how many expr expressions follow.
The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
"""
arrayExpr = Forward()
def countFieldParseAction(s,l,t):
n = int(t[0])
arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
return []
return ( Word(nums).setParseAction(countFieldParseAction) + arrayExpr )
 
def _flatten(L):
if type(L) is not list: return [L]
if L == []: return L
return _flatten(L[0]) + _flatten(L[1:])
 
def matchPreviousLiteral(expr):
"""Helper to define an expression that is indirectly defined from
the tokens matched in a previous expression, that is, it looks
for a 'repeat' of a previous expression. For example::
first = Word(nums)
second = matchPreviousLiteral(first)
matchExpr = first + ":" + second
will match "1:1", but not "1:2". Because this matches a
previous literal, will also match the leading "1:1" in "1:10".
If this is not desired, use matchPreviousExpr.
Do *not* use with packrat parsing enabled.
"""
rep = Forward()
def copyTokenToRepeater(s,l,t):
if t:
if len(t) == 1:
rep << t[0]
else:
# flatten t tokens
tflat = _flatten(t.asList())
rep << And( [ Literal(tt) for tt in tflat ] )
else:
rep << Empty()
expr.addParseAction(copyTokenToRepeater)
return rep
def matchPreviousExpr(expr):
"""Helper to define an expression that is indirectly defined from
the tokens matched in a previous expression, that is, it looks
for a 'repeat' of a previous expression. For example::
first = Word(nums)
second = matchPreviousExpr(first)
matchExpr = first + ":" + second
will match "1:1", but not "1:2". Because this matches by
expressions, will *not* match the leading "1:1" in "1:10";
the expressions are evaluated first, and then compared, so
"1" is compared with "10".
Do *not* use with packrat parsing enabled.
"""
rep = Forward()
e2 = expr.copy()
rep << e2
def copyTokenToRepeater(s,l,t):
matchTokens = _flatten(t.asList())
def mustMatchTheseTokens(s,l,t):
theseTokens = _flatten(t.asList())
if theseTokens != matchTokens:
raise ParseException("",0,"")
rep.setParseAction( mustMatchTheseTokens )
expr.addParseAction(copyTokenToRepeater)
return rep
def _escapeRegexRangeChars(s):
#~ escape these chars: ^-]
for c in r"\^-]":
s = s.replace(c,"\\"+c)
s = s.replace("\n",r"\n")
s = s.replace("\t",r"\t")
return _ustr(s)
def oneOf( strs, caseless=False, useRegex=True ):
"""Helper to quickly define a set of alternative Literals, and makes sure to do
longest-first testing when there is a conflict, regardless of the input order,
but returns a MatchFirst for best performance.
Parameters:
- strs - a string of space-delimited literals, or a list of string literals
- caseless - (default=False) - treat all literals as caseless
- useRegex - (default=True) - as an optimization, will generate a Regex
object; otherwise, will generate a MatchFirst object (if caseless=True, or
if creating a Regex raises an exception)
"""
if caseless:
isequal = ( lambda a,b: a.upper() == b.upper() )
masks = ( lambda a,b: b.upper().startswith(a.upper()) )
parseElementClass = CaselessLiteral
else:
isequal = ( lambda a,b: a == b )
masks = ( lambda a,b: b.startswith(a) )
parseElementClass = Literal
if isinstance(strs,(list,tuple)):
symbols = strs[:]
elif isinstance(strs,basestring):
symbols = strs.split()
else:
warnings.warn("Invalid argument to oneOf, expected string or list",
SyntaxWarning, stacklevel=2)
i = 0
while i < len(symbols)-1:
cur = symbols[i]
for j,other in enumerate(symbols[i+1:]):
if ( isequal(other, cur) ):
del symbols[i+j+1]
break
elif ( masks(cur, other) ):
del symbols[i+j+1]
symbols.insert(i,other)
cur = other
break
else:
i += 1
 
if not caseless and useRegex:
#~ print strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )
try:
if len(symbols)==len("".join(symbols)):
return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) )
else:
return Regex( "|".join( [ re.escape(sym) for sym in symbols] ) )
except:
warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
SyntaxWarning, stacklevel=2)
 
 
# last resort, just use MatchFirst
return MatchFirst( [ parseElementClass(sym) for sym in symbols ] )
 
def dictOf( key, value ):
"""Helper to easily and clearly define a dictionary by specifying the respective patterns
for the key and value. Takes care of defining the Dict, ZeroOrMore, and Group tokens
in the proper order. The key pattern can include delimiting markers or punctuation,
as long as they are suppressed, thereby leaving the significant key text. The value
pattern can include named results, so that the Dict results can include named token
fields.
"""
return Dict( ZeroOrMore( Group ( key + value ) ) )
 
_bslash = "\\"
printables = "".join( [ c for c in string.printable if c not in string.whitespace ] )
 
# convenience constants for positional expressions
empty = Empty().setName("empty")
lineStart = LineStart().setName("lineStart")
lineEnd = LineEnd().setName("lineEnd")
stringStart = StringStart().setName("stringStart")
stringEnd = StringEnd().setName("stringEnd")
 
_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
_printables_less_backslash = "".join([ c for c in printables if c not in r"\]" ])
_escapedHexChar = Combine( Suppress(_bslash + "0x") + Word(hexnums) ).setParseAction(lambda s,l,t:unichr(int(t[0],16)))
_escapedOctChar = Combine( Suppress(_bslash) + Word("0","01234567") ).setParseAction(lambda s,l,t:unichr(int(t[0],8)))
_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash,exact=1)
_charRange = Group(_singleChar + Suppress("-") + _singleChar)
_reBracketExpr = "[" + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
 
_expanded = lambda p: (isinstance(p,ParseResults) and ''.join([ unichr(c) for c in range(ord(p[0]),ord(p[1])+1) ]) or p)
def srange(s):
r"""Helper to easily define string ranges for use in Word construction. Borrows
syntax from regexp '[]' string range definitions::
srange("[0-9]") -> "0123456789"
srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz"
srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
The input string must be enclosed in []'s, and the returned string is the expanded
character set joined into a single string.
The values enclosed in the []'s may be::
a single character
an escaped character with a leading backslash (such as \- or \])
an escaped hex character with a leading '\0x' (\0x21, which is a '!' character)
an escaped octal character with a leading '\0' (\041, which is a '!' character)
a range of any of the above, separated by a dash ('a-z', etc.)
any combination of the above ('aeiouy', 'a-zA-Z0-9_$', etc.)
"""
try:
return "".join([_expanded(part) for part in _reBracketExpr.parseString(s).body])
except:
return ""
 
def replaceWith(replStr):
"""Helper method for common parse actions that simply return a literal value. Especially
useful when used with transformString().
"""
def _replFunc(*args):
return [replStr]
return _replFunc
 
def removeQuotes(s,l,t):
"""Helper parse action for removing quotation marks from parsed quoted strings.
To use, add this parse action to quoted string using::
quotedString.setParseAction( removeQuotes )
"""
return t[0][1:-1]
 
def upcaseTokens(s,l,t):
"""Helper parse action to convert tokens to upper case."""
return [ str(tt).upper() for tt in t ]
 
def downcaseTokens(s,l,t):
"""Helper parse action to convert tokens to lower case."""
return [ str(tt).lower() for tt in t ]
 
def keepOriginalText(s,startLoc,t):
import inspect
"""Helper parse action to preserve original parsed text,
overriding any nested parse actions."""
f = inspect.stack()[1][0]
try:
endloc = f.f_locals["loc"]
finally:
del f
return s[startLoc:endloc]
def _makeTags(tagStr, xml):
"""Internal helper to construct opening and closing tag expressions, given a tag name"""
tagAttrName = Word(alphanums)
if (xml):
tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
openTag = Suppress("<") + Keyword(tagStr) + \
Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
else:
printablesLessRAbrack = "".join( [ c for c in printables if c not in ">" ] )
tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
openTag = Suppress("<") + Keyword(tagStr,caseless=True) + \
Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
Suppress("=") + tagAttrValue ))) + \
Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
closeTag = Combine("</" + Keyword(tagStr,caseless=not xml) + ">")
openTag = openTag.setResultsName("start"+"".join(tagStr.replace(":"," ").title().split())).setName("<%s>" % tagStr)
closeTag = closeTag.setResultsName("end"+"".join(tagStr.replace(":"," ").title().split())).setName("</%s>" % tagStr)
return openTag, closeTag
 
def makeHTMLTags(tagStr):
"""Helper to construct opening and closing tag expressions for HTML, given a tag name"""
return _makeTags( tagStr, False )
 
def makeXMLTags(tagStr):
"""Helper to construct opening and closing tag expressions for XML, given a tag name"""
return _makeTags( tagStr, True )
 
opAssoc = _Constants()
opAssoc.LEFT = object()
opAssoc.RIGHT = object()
 
def operatorPrecedence( baseExpr, opList ):
"""Helper method for constructing grammars of expressions made up of
operators working in a precedence hierarchy. Operators may be unary or
binary, left- or right-associative. Parse actions can also be attached
to operator expressions.
Parameters:
- baseExpr - expression representing the most basic element for the nested
- opList - list of tuples, one for each operator precedence level in the expression grammar; each tuple is of the form
(opExpr, numTerms, rightLeftAssoc, parseAction), where:
- opExpr is the pyparsing expression for the operator;
may also be a string, which will be converted to a Literal
- numTerms is the number of terms for this operator (must
be 1 or 2)
- rightLeftAssoc is the indicator whether the operator is
right or left associative, using the pyparsing-defined
constants opAssoc.RIGHT and opAssoc.LEFT.
- parseAction is the parse action to be associated with
expressions matching this operator expression (the
parse action tuple member may be omitted)
"""
ret = Forward()
lastExpr = baseExpr | ( Suppress('(') + ret + Suppress(')') )
for i,operDef in enumerate(opList):
opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4]
thisExpr = Forward().setName("expr%d" % i)
if rightLeftAssoc == opAssoc.LEFT:
if arity == 1:
matchExpr = Group( lastExpr + opExpr )
elif arity == 2:
matchExpr = Group( lastExpr + OneOrMore( opExpr + lastExpr ) )
else:
raise ValueError, "operator must be unary (1) or binary (2)"
elif rightLeftAssoc == opAssoc.RIGHT:
if arity == 1:
# try to avoid LR with this extra test
if not isinstance(opExpr, Optional):
opExpr = Optional(opExpr)
matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr )
elif arity == 2:
matchExpr = Group( lastExpr + OneOrMore( opExpr + thisExpr ) )
else:
raise ValueError, "operator must be unary (1) or binary (2)"
else:
raise ValueError, "operator must indicate right or left associativity"
if pa:
matchExpr.setParseAction( pa )
thisExpr << ( matchExpr | lastExpr )
lastExpr = thisExpr
ret << lastExpr
return ret
 
alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xfe]")
 
dblQuotedString = Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\.))*"').setName("string enclosed in double quotes")
sglQuotedString = Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\.))*'").setName("string enclosed in single quotes")
quotedString = Regex(r'''(?:"(?:[^"\n\r\\]|(?:"")|(?:\\.))*")|(?:'(?:[^'\n\r\\]|(?:'')|(?:\\.))*')''').setName("quotedString using single or double quotes")
 
# it's easy to get these comment structures wrong - they're very common, so may as well make them available
cStyleComment = Regex(r"/\*(?:[^*]*\*+)+?/").setName("C style comment")
 
htmlComment = Regex(r"<!--[\s\S]*?-->")
restOfLine = Regex(r".*").leaveWhitespace()
dblSlashComment = Regex(r"\/\/(\\\n|.)*").setName("// comment")
cppStyleComment = Regex(r"/(?:\*(?:[^*]*\*+)+?/|/[^\n]*(?:\n[^\n]*)*?(?:(?<!\\)|\Z))").setName("C++ style comment")
 
javaStyleComment = cppStyleComment
pythonStyleComment = Regex(r"#.*").setName("Python style comment")
_noncomma = "".join( [ c for c in printables if c != "," ] )
_commasepitem = Combine(OneOrMore(Word(_noncomma) +
Optional( Word(" \t") +
~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem")
commaSeparatedList = delimitedList( Optional( quotedString | _commasepitem, default="") ).setName("commaSeparatedList")
 
 
if __name__ == "__main__":
 
def test( teststring ):
print teststring,"->",
try:
tokens = simpleSQL.parseString( teststring )
tokenlist = tokens.asList()
print tokenlist
print "tokens = ", tokens
print "tokens.columns =", tokens.columns
print "tokens.tables =", tokens.tables
print tokens.asXML("SQL",True)
except ParseException, err:
print err.line
print " "*(err.column-1) + "^"
print err
print
 
selectToken = CaselessLiteral( "select" )
fromToken = CaselessLiteral( "from" )
 
ident = Word( alphas, alphanums + "_$" )
columnName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
columnNameList = Group( delimitedList( columnName ) )#.setName("columns")
tableName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens )
tableNameList = Group( delimitedList( tableName ) )#.setName("tables")
simpleSQL = ( selectToken + \
( '*' | columnNameList ).setResultsName( "columns" ) + \
fromToken + \
tableNameList.setResultsName( "tables" ) )
test( "SELECT * from XYZZY, ABC" )
test( "select * from SYS.XYZZY" )
test( "Select A from Sys.dual" )
test( "Select AA,BB,CC from Sys.dual" )
test( "Select A, B, C from Sys.dual" )
test( "Select A, B, C from Sys.dual" )
test( "Xelect A, B, C from Sys.dual" )
test( "Select A, B, C frox Sys.dual" )
test( "Select" )
test( "Select ^^^ frox Sys.dual" )
test( "Select A, B, C from Sys.dual, Table2 " )
/tags/arelease/documentation/instructioncoding.txt
0,0 → 1,173
====================================================
HiCoVec Processor Instruction Set & Coding
====================================================
 
www.opencores.org/projects/hicovec
 
This document originates from Prof. Dr.-Ing. Gundolf Kiefer, teaching at the University of Applied Sciences in Augsburg.
It is the fundament of the HiCoVec processor. While being vital during the development of the processor, it
now serves the purpose of providing detailed information about the instruction set and coding for people trying
to write applications.
 
 
General
===========
- Each intruction word consists of exactly 32 bit. This makes instruction decoding and execution pretty simple.
- With a few exceptions, the first 12 bit define a scalar operation and the following 20 bit a vector operation. (VLIW/EPIC-Principle)
- "000" encodes the NOP-command, thereby allowing the other unit (scalar/vector) to use the remaining bits.
 
Harware components:
- instruction register (32 Bit)
- memory interface
- scalar unit
- vector unit
 
Scalar unit
==============
Principle:
- accumulator machine
- load/store architecture
- addressing modes: absolute, register indirect, register indirect with displacement
- address calculation using ALU (ADD-operation)
 
Hardware components:
- register: A, X, Y (each 32 bit)
- flags: Carry, Zero
- ALU
- instruction counter
- control unit
- some multiplexers
 
ALU commands:
01 oooo dd ss tt -------------------- respectivly
01 oooo dd ss 00 000-nnnnnnnnnnnnnnnn <Op> d, s, t
 
d: destination register: 00 = none, 01 = A, 10 = X, 11 = Y
s: 1. source register: 00 = 0 , 01 = A, 10 = X, 11 = Y
t: 2. source register: 00 = n , 01 = A, 10 = X, 11 = Y
 
o: operation
0000: ADD 0001: ADC
0010: SUB 0011: SBC
0100: INC
0110: DEC
1000: AND 1001: OR
1010: XOR 1011: MUL (optional)
1100: LSL (insert 0) 1101: ROL (insert carry)
1110: LSR (insert 0) 1111: ROR (insert carry)
 
load/store commands:
10 00-- dd ss tt -------------------- respectivly
10 00-- dd ss 00 000-nnnnnnnnnnnnnnnn LD d, s + t
10 10-- -- ss tt -------------------- respectivly
10 10-- -- ss 00 000-nnnnnnnnnnnnnnnn ST s + t, A
 
Legwork for vector unit (here just scalar part, for full details look below):
10 01-- -- ss tt -------------------- VLD ..., s + t ; t != 00
10 1100 -- ss tt -------------------- VST s + t, ... ; t != 00
10 1110 -- ss -- -------------------- MOV r(...), s ; t != 00
10 1111 dd -- -- -------------------- MOV d, v(...) ; t != 00
10 1101 -- ss -- -------------------- MOVA r, s
 
Jump commands:
00 0--- -- -- -- -------------------- NOP
00 1000 00 ss tt -------------------- JMP s+t
00 1000 dd ss tt -------------------- JAL A/X/Y, s+t ; Jump-And-Link (useful for subprograms)
00 101- -- -- -- -------------------- HALT
00 1100 00 ss tt -------------------- JNC s+t
00 1101 00 ss tt -------------------- JC s+t
00 1110 00 ss tt -------------------- JNZ s+t
00 1111 00 ss tt -------------------- JZ s+t
 
Other:
11 0000 -- ee ff -------------------- set/clear flags
ee: select flag (Z, C) CLC, CLZ, SEC, SEZ
ff: new value
e.g.:
11 0000 -- 01 -0 -------------------- CLC (clear carry)
 
 
Vector unit
==============
Principle:
- N registers, each K * 32 bit wide
- N, K are configurable
- Direct access is only possible for R0 to R15. The other registers can be used as temporary storage using
the VMOV command.
- Wordlength of an operation can be specified (following Intel naming convention)
- QW = Quadword (64 bit)
- DW = Doubleword (32 bit)
- W = Word (16 bit)
- B = Byte (8 bit)
 
- N, K can choosed freely. Instruction decoding is independant of selected values with the following
exceptions:
* K has to be dividable by 2 (otherweise the 64 bit mode would be silly)
* N can not exceed 16 in instruction words (the rest is adressable via VMOV command)
* VSHUF wordlength is K * 32 / 4
 
Hardware components:
- N register, each K * 32 bit wide (N, K configurable)
- K 32 bit ALUs
- vector control unit
- shuffle unit
- select unit (used to select data for transfer to scalar unit)
- vector ALU control unit
- some multiplexers
 
 
VALU commands:
------------ 01 ww oooo rrrr vvvv wwww <Op> (.B/.W/.DW/.QW) r, v, w
 
w: wordlength: 00 = 8 Bit, 01 = 16 Bit, 10 = 32 Bit, 11 = 64 Bit
r: destination vectorregister (R0...R7)
v: 1. source vectorregister (R0...R7)
w: 2. source vektorregister (R0...R7)
 
o: Operation
0000: VADD
0010: VSUB
1000: VAND
1001: VOR
1010: VXOR
1011: VMUL (optional)
1100: VLSL
1110: VLSR
 
Transfer commands (in cooperation with scalar unit):
10 01-- -- ss tt 10 -- 0010 rrrr ---- ---- VLD r, s + t ; t != 00
10 1100 -- ss tt 10 -- 0011 --- vvvv ---- VST s + t, v ; t != 00
10 1101 -- ss -- 10 -- 0110 rrrr ---- ---- MOVA r, s ;
10 1110 -- ss tt 10 -- 0100 rrrr ---- ---- MOV r(t), s ; t != 00
10 1111 dd -- tt 10 -- 0101 ---- vvvv ---- MOV d, v(t) ; t != 00
 
Shuffle command: (BITORDER REVERSED !!!)
000-nnnnnnnn 11 ww ssss rrrr vvvv wwww VSHUF r,v,w,wwssssnnnnnnnn
 
VSHUF allows fast, parallel transfer of data inside of or between vector registers.
w defines a wordlength W <= 32*K/4. r[i], v[i] and w[i] are i-th partial words of or vector
register r, v and w. n[i] defines the i-th bit group of n und s[i] the i-th bit von n.
For i <= 3:
r[i] <- v[n[i]], if s[i] = 0
r[i] <- w[n[i]], if s[i] = 1
General:
r[i] <- v[n[i % 4] + i/4], if s[i % 4] = 0
r[i] <- w[n[i % 4] + i/4], if s[i % 4] = 1
 
Example:
Command: VSHUF R2, 16, R3:2, R3:3, R5:1, R5:2
Coding: nnnnnnnn = 10 11 01 10, ssss = 0011, vvvv = 3, wwww = 5
Effect: R2(31:0) <- R3(63:32), R2(63:32) <- R5(47:16)
 
Other:
------------ 00 0- ---- ---- ---- ---- VNOP
------------ 00 1- 1000 rrrr vvvv ---- VMOL r,v
------------ 00 1- 1100 rrrr vvvv ---- VMOR r,v
------------ 00 1- 0001 rrrr vvvv ---- VMOV r, v
000-nnnnnnnn 00 1- 0010 rrrr ---- ---- VMOV r, R<n>
000-nnnnnnnn 00 1- 0011 ---- vvvv ---- VMOV R<n>, v
 
/tags/arelease/documentation/diplomathesis.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
tags/arelease/documentation/diplomathesis.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/arelease/instructioncoding.txt =================================================================== --- tags/arelease/instructioncoding.txt (nonexistent) +++ tags/arelease/instructioncoding.txt (revision 10) @@ -0,0 +1,173 @@ +==================================================== + HiCoVec Processor Instruction Set & Coding +==================================================== + +www.opencores.org/projects/hicovec + +This document originates from Prof. Dr.-Ing. Gundolf Kiefer, teaching at the University of Applied Sciences in Augsburg. +It is the fundament of the HiCoVec processor. While being vital during the development of the processor, it +now serves the purpose of providing detailed information about the instruction set and coding for people trying +to write applications. + + +General +=========== +- Each intruction word consists of exactly 32 bit. This makes instruction decoding and execution pretty simple. +- With a few exceptions, the first 12 bit define a scalar operation and the following 20 bit a vector operation. (VLIW/EPIC-Principle) +- "000" encodes the NOP-command, thereby allowing the other unit (scalar/vector) to use the remaining bits. + +Harware components: +- instruction register (32 Bit) +- memory interface +- scalar unit +- vector unit + +Scalar unit +============== +Principle: +- accumulator machine +- load/store architecture +- addressing modes: absolute, register indirect, register indirect with displacement + - address calculation using ALU (ADD-operation) + +Hardware components: +- register: A, X, Y (each 32 bit) +- flags: Carry, Zero +- ALU +- instruction counter +- control unit +- some multiplexers + +ALU commands: + 01 oooo dd ss tt -------------------- respectivly + 01 oooo dd ss 00 000-nnnnnnnnnnnnnnnn d, s, t + + d: destination register: 00 = none, 01 = A, 10 = X, 11 = Y + s: 1. source register: 00 = 0 , 01 = A, 10 = X, 11 = Y + t: 2. source register: 00 = n , 01 = A, 10 = X, 11 = Y + + o: operation + 0000: ADD 0001: ADC + 0010: SUB 0011: SBC + 0100: INC + 0110: DEC + 1000: AND 1001: OR + 1010: XOR 1011: MUL (optional) + 1100: LSL (insert 0) 1101: ROL (insert carry) + 1110: LSR (insert 0) 1111: ROR (insert carry) + +load/store commands: + 10 00-- dd ss tt -------------------- respectivly + 10 00-- dd ss 00 000-nnnnnnnnnnnnnnnn LD d, s + t + 10 10-- -- ss tt -------------------- respectivly + 10 10-- -- ss 00 000-nnnnnnnnnnnnnnnn ST s + t, A + +Legwork for vector unit (here just scalar part, for full details look below): + 10 01-- -- ss tt -------------------- VLD ..., s + t ; t != 00 + 10 1100 -- ss tt -------------------- VST s + t, ... ; t != 00 + + 10 1110 -- ss -- -------------------- MOV r(...), s ; t != 00 + 10 1111 dd -- -- -------------------- MOV d, v(...) ; t != 00 + 10 1101 -- ss -- -------------------- MOVA r, s + +Jump commands: + 00 0--- -- -- -- -------------------- NOP + 00 1000 00 ss tt -------------------- JMP s+t + 00 1000 dd ss tt -------------------- JAL A/X/Y, s+t ; Jump-And-Link (useful for subprograms) + 00 101- -- -- -- -------------------- HALT + 00 1100 00 ss tt -------------------- JNC s+t + 00 1101 00 ss tt -------------------- JC s+t + 00 1110 00 ss tt -------------------- JNZ s+t + 00 1111 00 ss tt -------------------- JZ s+t + +Other: + 11 0000 -- ee ff -------------------- set/clear flags + ee: select flag (Z, C) CLC, CLZ, SEC, SEZ + ff: new value + e.g.: + 11 0000 -- 01 -0 -------------------- CLC (clear carry) + + +Vector unit +============== +Principle: +- N registers, each K * 32 bit wide +- N, K are configurable +- Direct access is only possible for R0 to R15. The other registers can be used as temporary storage using + the VMOV command. +- Wordlength of an operation can be specified (following Intel naming convention) + - QW = Quadword (64 bit) + - DW = Doubleword (32 bit) + - W = Word (16 bit) + - B = Byte (8 bit) + +- N, K can choosed freely. Instruction decoding is independant of selected values with the following + exceptions: + * K has to be dividable by 2 (otherweise the 64 bit mode would be silly) + * N can not exceed 16 in instruction words (the rest is adressable via VMOV command) + * VSHUF wordlength is K * 32 / 4 + +Hardware components: +- N register, each K * 32 bit wide (N, K configurable) +- K 32 bit ALUs +- vector control unit +- shuffle unit +- select unit (used to select data for transfer to scalar unit) +- vector ALU control unit +- some multiplexers + + +VALU commands: + ------------ 01 ww oooo rrrr vvvv wwww (.B/.W/.DW/.QW) r, v, w + + w: wordlength: 00 = 8 Bit, 01 = 16 Bit, 10 = 32 Bit, 11 = 64 Bit + r: destination vectorregister (R0...R7) + v: 1. source vectorregister (R0...R7) + w: 2. source vektorregister (R0...R7) + + o: Operation + 0000: VADD + 0010: VSUB + 1000: VAND + 1001: VOR + 1010: VXOR + 1011: VMUL (optional) + 1100: VLSL + 1110: VLSR + + +Transfer commands (in cooperation with scalar unit): + 10 01-- -- ss tt 10 -- 0010 rrrr ---- ---- VLD r, s + t ; t != 00 + 10 1100 -- ss tt 10 -- 0011 --- vvvv ---- VST s + t, v ; t != 00 + 10 1101 -- ss -- 10 -- 0110 rrrr ---- ---- MOVA r, s ; + 10 1110 -- ss tt 10 -- 0100 rrrr ---- ---- MOV r(t), s ; t != 00 + 10 1111 dd -- tt 10 -- 0101 ---- vvvv ---- MOV d, v(t) ; t != 00 + + +Shuffle command: (BITORDER REVERSED !!!) + 000-nnnnnnnn 11 ww ssss rrrr vvvv wwww VSHUF r,v,w,wwssssnnnnnnnn + + VSHUF allows fast, parallel transfer of data inside of or between vector registers. + w defines a wordlength W <= 32*K/4. r[i], v[i] and w[i] are i-th partial words of or vector + register r, v and w. n[i] defines the i-th bit group of n und s[i] the i-th bit von n. + + For i <= 3: + r[i] <- v[n[i]], if s[i] = 0 + r[i] <- w[n[i]], if s[i] = 1 + General: + r[i] <- v[n[i % 4] + i/4], if s[i % 4] = 0 + r[i] <- w[n[i % 4] + i/4], if s[i % 4] = 1 + + Example: + Command: VSHUF R2, 16, R3:2, R3:3, R5:1, R5:2 + Coding: nnnnnnnn = 10 11 01 10, ssss = 0011, vvvv = 3, wwww = 5 + Effect: R2(31:0) <- R3(63:32), R2(63:32) <- R5(47:16) + +Other: + ------------ 00 0- ---- ---- ---- ---- VNOP + ------------ 00 1- 1000 rrrr vvvv ---- VMOL r,v + ------------ 00 1- 1100 rrrr vvvv ---- VMOR r,v + ------------ 00 1- 0001 rrrr vvvv ---- VMOV r, v + 000-nnnnnnnn 00 1- 0010 rrrr ---- ---- VMOV r, R + 000-nnnnnnnn 00 1- 0011 ---- vvvv ---- VMOV R, v + Index: tags/arelease/diplomathesis.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/arelease/diplomathesis.pdf =================================================================== --- tags/arelease/diplomathesis.pdf (nonexistent) +++ tags/arelease/diplomathesis.pdf (revision 10)
tags/arelease/diplomathesis.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/arelease/cpu/groups/registergroup.vhd =================================================================== --- tags/arelease/cpu/groups/registergroup.vhd (nonexistent) +++ tags/arelease/cpu/groups/registergroup.vhd (revision 10) @@ -0,0 +1,127 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: registergroup +-- +-- PURPOSE: register file and destination multiplexer +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity registergroup is + port( -- clock + clk: in std_logic; + + -- data inputs + result_in: in std_logic_vector(31 downto 0); -- data from alu + vector_in: in std_logic_vector(31 downto 0); -- data from vector unit + ic_in: in std_logic_vector(31 downto 0); -- instruction + enable_in: in std_logic; -- c6 + + -- data outputs + x_out: out std_logic_vector(31 downto 0); + y_out: out std_logic_vector(31 downto 0); + a_out: out std_logic_vector(31 downto 0); + + -- control signals + sel_source: in std_logic_vector(1 downto 0); -- cc2 + sel_dest: in std_logic_vector(1 downto 0) -- dd + ); +end registergroup; + +architecture rtl of registergroup is + component dataregister + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + component multiplexer4 + generic ( + w : positive + ); + port ( + selector: in std_logic_vector(1 downto 0); + data_in_00: in std_logic_vector(w-1 downto 0); + data_in_01: in std_logic_vector(w-1 downto 0); + data_in_10: in std_logic_vector(w-1 downto 0); + data_in_11: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + component demultiplexer1x4 + port( selector: in std_logic_vector(1 downto 0); + data_in: in std_logic; + data_out_00: out std_logic; + data_out_01: out std_logic; + data_out_10: out std_logic; + data_out_11: out std_logic + ); + end component; + + for reg_x: dataregister use entity work.dataregister(rtl); + for reg_y: dataregister use entity work.dataregister(rtl); + for reg_a: dataregister use entity work.dataregister(rtl); + + for mux_input: multiplexer4 use entity work.multiplexer4(rtl); + for demux: demultiplexer1x4 use entity work.demultiplexer1x4(rtl); + + signal data_in: std_logic_vector(31 downto 0); + signal load_x: std_logic; + signal load_y: std_logic; + signal load_a: std_logic; + + begin + mux_input: multiplexer4 + generic map ( + w => 32 + ) + port map ( + selector => sel_source, + data_in_00 => result_in, + data_in_01 => ic_in, + data_in_10 => vector_in, + data_in_11 => "--------------------------------", + data_out => data_in + ); + + demux: demultiplexer1x4 port map ( + selector => sel_dest, + data_in => enable_in, + data_out_00 => open, + data_out_01 => load_a, + data_out_10 => load_x, + data_out_11 => load_y + ); + + reg_x: dataregister port map( + clk => clk, + load => load_x, + data_in => data_in, + data_out => x_out + ); + + reg_y: dataregister port map( + clk => clk, + load => load_y, + data_in => data_in, + data_out => y_out + ); + + reg_a: dataregister port map( + clk => clk, + load => load_a, + data_in => data_in, + data_out => a_out + ); + +end rtl; \ No newline at end of file Index: tags/arelease/cpu/groups/vector_slice.vhd =================================================================== --- tags/arelease/cpu/groups/vector_slice.vhd (nonexistent) +++ tags/arelease/cpu/groups/vector_slice.vhd (revision 10) @@ -0,0 +1,177 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: vector_slice +-- +-- PURPOSE: slice of the vector executionunit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity vector_slice is + generic ( + slicenr : natural := 0 + ); + port ( + -- clock + clk: in std_logic; + + -- data inputs + memory_in: in std_logic_vector(31 downto 0); + scalar_in: in std_logic_vector(31 downto 0); + shuffle_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + rshift_in: in std_logic; + + -- data outputs + v_out: out std_logic_vector(31 downto 0); + w_out: out std_logic_vector(31 downto 0); + carry_out: out std_logic; + + -- control signals + rrrr: in std_logic_vector(7 downto 0); + vvvv: in std_logic_vector(7 downto 0); + wwww: in std_logic_vector(3 downto 0); + k_in: in std_logic_vector(31 downto 0); + load_r: in std_logic; + cc9: in std_logic_vector(1 downto 0); + c12: in std_logic; + + -- valu control signals + valuop: in std_logic_vector(3 downto 0); + source_sel: in std_logic_vector(1 downto 0); + carry_sel: in std_logic_vector(1 downto 0); + mult_source_sel: in std_logic_vector(1 downto 0); -- * + mult_dest_sel: in std_logic_vector(1 downto 0); -- * + reg_input_sel: in std_logic; -- * + load_lsr: in std_logic; + load_other: in std_logic + ); +end vector_slice; + +architecture rtl of vector_slice is + component multiplexer4 + generic ( + w : positive + ); + port ( + selector: in std_logic_vector(1 downto 0); + data_in_00: in std_logic_vector(w-1 downto 0); + data_in_01: in std_logic_vector(w-1 downto 0); + data_in_10: in std_logic_vector(w-1 downto 0); + data_in_11: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + + component vector_alu_32 + port( + clk: in std_logic; + v_in: in std_logic_vector(31 downto 0); + w_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + rshift_in: in std_logic; + carry_out: out std_logic; + valu_out: out std_logic_vector(31 downto 0); + valuop: in std_logic_vector(3 downto 0); + source_sel: in std_logic_vector(1 downto 0); + carry_sel: in std_logic_vector(1 downto 0); + mult_source_sel: in std_logic_vector(1 downto 0); + mult_dest_sel: in std_logic_vector(1 downto 0); + reg_input_sel: in std_logic; + load_lsr: in std_logic; + load_other: in std_logic + ); + end component; + + component vector_register + generic ( + n : integer range 1 to 256; + slicenr : natural + ); + + port ( + clk: in std_logic; + r_in: in std_logic_vector(31 downto 0); + v_out: out std_logic_vector(31 downto 0); + w_out: out std_logic_vector(31 downto 0); + load_r: in std_logic; + load_select: in std_logic; + k_in: in std_logic_vector(31 downto 0); + select_v: in std_logic_vector(7 downto 0); + select_w: in std_logic_vector(3 downto 0); + select_r: in std_logic_vector(7 downto 0) + ); + end component; + + for vreg_input_mux: multiplexer4 use entity work.multiplexer4(rtl); + for valu: vector_alu_32 use entity work.vector_alu_32(rtl); + for vreg: vector_register use entity work.vector_register(rtl); + + signal v: std_logic_vector(31 downto 0); + signal w: std_logic_vector(31 downto 0); + signal r: std_logic_vector(31 downto 0); + signal valu_result: std_logic_vector(31 downto 0); + +begin + v_out <= v; + w_out <= w; + + vreg_input_mux: multiplexer4 + generic map (w => 32) + port map ( + selector => cc9, + data_in_00 => valu_result, + data_in_01 => scalar_in, + data_in_10 => memory_in, + data_in_11 => shuffle_in, + data_out => r + ); + + vreg: vector_register + generic map ( + n => n, + slicenr => slicenr + ) + port map ( + clk => clk, + r_in => r, + v_out => v, + w_out => w, + load_r => load_r, + load_select => c12, + k_in => k_in, + select_v => vvvv, + select_w => wwww, + select_r => rrrr + ); + + valu: vector_alu_32 + port map ( + clk => clk, + v_in => v, + w_in => w, + carry_in => carry_in, + rshift_in => rshift_in, + carry_out => carry_out, + valu_out => valu_result, + valuop => valuop, + source_sel => source_sel, + carry_sel => carry_sel, + mult_source_sel => mult_source_sel, + mult_dest_sel => mult_dest_sel, + reg_input_sel => reg_input_sel, + load_lsr => load_lsr, + load_other => load_other + ); + +end rtl; \ No newline at end of file Index: tags/arelease/cpu/groups/addressgroup.vhd =================================================================== --- tags/arelease/cpu/groups/addressgroup.vhd (nonexistent) +++ tags/arelease/cpu/groups/addressgroup.vhd (revision 10) @@ -0,0 +1,89 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: addressgroup +-- +-- PURPOSE: consists of and connects components +-- used for adressing the memory interface +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity addressgroup is + port( -- clock + clk: in std_logic; + + -- data inputs + address_in: in std_logic_vector(31 downto 0); + + -- data outputs + address_out: out std_logic_vector(31 downto 0); + ic_out: out std_logic_vector(31 downto 0); + + -- control signals + sel_source: in std_logic; -- c1 + inc: in std_logic; + load_ic: in std_logic; + reset_ic: in std_logic + ); +end addressgroup; + +architecture rtl of addressgroup is + component instructioncounter + port( clk: in std_logic; + load: in std_logic; + inc: in std_logic; + reset: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + component multiplexer2 + generic ( + w : positive -- word width + ); + port ( + selector: in std_logic; + data_in_0: in std_logic_vector(w-1 downto 0); + data_in_1: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + + for ic: instructioncounter use entity work.instructioncounter(rtl); + for mux: multiplexer2 use entity work.multiplexer2(rtl); + + + signal instruction: std_logic_vector(31 downto 0); + + begin + ic: instructioncounter port map ( + clk => clk, + load => load_ic, + inc => inc, + reset => reset_ic, + data_in => address_in, + data_out => instruction + ); + + mux: multiplexer2 + generic map ( + w => 32 + ) + port map ( + selector => sel_source, + data_in_0 => instruction, + data_in_1 => address_in, + data_out => address_out + ); + + ic_out <= instruction; +end rtl; \ No newline at end of file Index: tags/arelease/cpu/groups/vector_executionunit.vhd =================================================================== --- tags/arelease/cpu/groups/vector_executionunit.vhd (nonexistent) +++ tags/arelease/cpu/groups/vector_executionunit.vhd (revision 10) @@ -0,0 +1,302 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: vector_executionunit +-- +-- PURPOSE: execution unit of the vector unit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity vector_executionunit is + port ( + -- clock + clk: in std_logic; + + -- data inputs + memory_in: in vectordata_type; + scalar_in: in std_logic_vector(31 downto 0); + + -- data outputs + memory_out: out vectordata_type; + scalar_out: out std_logic_vector(31 downto 0); + out_valid: out std_logic; + shuffle_valid: out std_logic; + + -- control signals + rrrr: in std_logic_vector(3 downto 0); + vvvv: in std_logic_vector(3 downto 0); + wwww: in std_logic_vector(3 downto 0); + k_in: in std_logic_vector(31 downto 0); + vn: in std_logic_vector(7 downto 0); -- immediate value n for vector unit + valuop: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + load_r: in std_logic; + cc9: in std_logic_vector(1 downto 0); + c10: in std_logic; + c11: in std_logic; + c12: in std_logic; + cc13: in std_logic_vector(1 downto 0); + valu_go: in std_logic; + shuffle_go: in std_logic + ); +end vector_executionunit; + +architecture rtl of vector_executionunit is + component selectunit + port ( + data_in : in vectordata_type; + k_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + component shuffle + port ( + clk: in std_logic; + shuffle_go: in std_logic; + shuffle_valid: out std_logic; + data_in_v: in vectordata_type; + data_in_w: in vectordata_type; + vn: in std_logic_vector(7 downto 0); + ssss: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + shuffle_out_sel: in std_logic_vector(1 downto 0); + data_out: out vectordata_type + ); + end component; + + component valu_controlunit + port( + clk: in std_logic; + valu_go: in std_logic; + valuop: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + source_sel: out std_logic_vector(1 downto 0); + carry_sel: out std_logic_vector(1 downto 0); + mult_source_sel: out std_logic_vector(1 downto 0); + mult_dest_sel: out std_logic_vector(1 downto 0); + reg_input_sel: out std_logic; + load_lsr: out std_logic; + load_other: out std_logic; + out_valid: out std_logic + ); + end component; + + component vector_slice + generic ( + slicenr : natural := 0 + ); + port ( + clk: in std_logic; + memory_in: in std_logic_vector(31 downto 0); + scalar_in: in std_logic_vector(31 downto 0); + shuffle_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + rshift_in: in std_logic; + v_out: out std_logic_vector(31 downto 0); + w_out: out std_logic_vector(31 downto 0); + carry_out: out std_logic; + rrrr: in std_logic_vector(7 downto 0); + vvvv: in std_logic_vector(7 downto 0); + wwww: in std_logic_vector(3 downto 0); + k_in: in std_logic_vector(31 downto 0); + load_r: in std_logic; + cc9: in std_logic_vector(1 downto 0); + c12: in std_logic; + valuop: in std_logic_vector(3 downto 0); + source_sel: in std_logic_vector(1 downto 0); + carry_sel: in std_logic_vector(1 downto 0); + mult_source_sel: in std_logic_vector(1 downto 0); + mult_dest_sel: in std_logic_vector(1 downto 0); + reg_input_sel: in std_logic; + load_lsr: in std_logic; + load_other: in std_logic + ); + end component; + + component multiplexer2 + generic ( + w : positive + ); + port( + selector: in std_logic; + data_in_0: in std_logic_vector(w-1 downto 0); + data_in_1: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + for shuffle_impl: shuffle use entity work.shuffle(rtl); + for selectunit_impl: selectunit use entity work.selectunit(rtl); + for valu_controlunit_impl: valu_controlunit use entity work.valu_controlunit(rtl); + + for rrrr_mux: multiplexer2 use entity work.multiplexer2(rtl); + for vvvv_mux: multiplexer2 use entity work.multiplexer2(rtl); + + signal carry : std_logic_vector(k-1 downto 0); + signal v_vector : vectordata_type; + signal w_vector : vectordata_type; + signal shuffle_out : vectordata_type; + signal select_v : std_logic_vector(7 downto 0); + signal select_r : std_logic_vector(7 downto 0); + + signal sel_r : std_logic_vector(7 downto 0); + signal sel_v : std_logic_vector(7 downto 0); + signal sel_w : std_logic_vector(3 downto 0); + + signal rrrr_ext : std_logic_vector(7 downto 0); + signal vvvv_ext : std_logic_vector(7 downto 0); + + signal source_sel: std_logic_vector(1 downto 0); + signal carry_sel: std_logic_vector(1 downto 0); + signal mult_source_sel: std_logic_vector(1 downto 0); + signal mult_dest_sel: std_logic_vector(1 downto 0); + signal reg_input_sel: std_logic; + signal load_lsr: std_logic; + signal load_other: std_logic; + +begin + rrrr_ext <= "0000" & rrrr; + vvvv_ext <= "0000" & vvvv; + + rrrr_mux : multiplexer2 + generic map (w => 8) + port map ( + selector => c10, + data_in_0 => rrrr_ext, + data_in_1 => vn, + data_out => select_r + ); + + + vvvv_mux : multiplexer2 + generic map (w => 8) + port map ( + selector => c11, + data_in_0 => vvvv_ext, + data_in_1 => vn, + data_out => select_v + ); + + -- check index < n + sel_r <= select_r when (select_r < n) else (others => '0'); + sel_v <= select_v when (select_v < n) else (others => '0'); + sel_w <= wwww when (wwww < n) else (others => '0'); + + selectunit_impl: selectunit + port map ( + data_in => v_vector, + k_in => k_in, + data_out => scalar_out + ); + + shuffle_impl: shuffle + port map ( + clk => clk, + shuffle_go => shuffle_go, + shuffle_valid => shuffle_valid, + data_in_v => v_vector, + data_in_w => w_vector, + vn => vn, + ssss => valuop, + vwidth => vwidth, + shuffle_out_sel => cc13, + data_out => shuffle_out + ); + + valu_controlunit_impl: valu_controlunit + port map ( + clk => clk, + valu_go => valu_go, + valuop => valuop, + vwidth => vwidth, + source_sel => source_sel, + carry_sel => carry_sel, + mult_source_sel => mult_source_sel, + mult_dest_sel => mult_dest_sel, + reg_input_sel => reg_input_sel, + load_lsr => load_lsr, + load_other => load_other, + out_valid => out_valid + ); + + vector_slice_impl: for i in k-1 downto 0 generate + vector_slice_even: if i mod 2 = 0 generate + slice_even: vector_slice + generic map ( + slicenr => i + ) + port map ( + clk => clk, + memory_in => memory_in(i), + scalar_in => scalar_in, + shuffle_in => shuffle_out(i), + carry_in => '0', + rshift_in => carry(i+1), + v_out => v_vector(i), + w_out => w_vector(i), + carry_out => carry(i), + rrrr => sel_r, + vvvv => sel_v, + wwww => sel_w, + k_in => k_in, + load_r => load_r, + cc9 => cc9, + c12 => c12, + valuop => valuop, + source_sel => source_sel, + carry_sel => carry_sel, + mult_source_sel => mult_source_sel, + mult_dest_sel => mult_dest_sel, + reg_input_sel => reg_input_sel, + load_lsr => load_lsr, + load_other => load_other + ); + end generate; + + vector_slice_uneven: if i mod 2 = 1 generate + slice_uneven: vector_slice + generic map ( + slicenr => i + ) + port map ( + clk => clk, + memory_in => memory_in(i), + scalar_in => scalar_in, + shuffle_in => shuffle_out(i), + carry_in => carry(i-1), + rshift_in => '0', + v_out => v_vector(i), + w_out => w_vector(i), + carry_out => carry(i), + rrrr => sel_r, + vvvv => sel_v, + wwww => sel_w, + k_in => k_in, + load_r => load_r, + cc9 => cc9, + c12 => c12, + valuop => valuop, + source_sel => source_sel, + carry_sel => carry_sel, + mult_source_sel => mult_source_sel, + mult_dest_sel => mult_dest_sel, + reg_input_sel => reg_input_sel, + load_lsr => load_lsr, + load_other => load_other + ); + end generate; + end generate ; + + memory_out <= v_vector; + +end rtl; \ No newline at end of file Index: tags/arelease/cpu/groups/flaggroup.vhd =================================================================== --- tags/arelease/cpu/groups/flaggroup.vhd (nonexistent) +++ tags/arelease/cpu/groups/flaggroup.vhd (revision 10) @@ -0,0 +1,113 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: flaggroup +-- +-- PURPOSE: status register, flags +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity flaggroup is + port( -- clock + clk: in std_logic; + + -- data inputs + c_in: in std_logic; + z_in: in std_logic; + + -- data outputs + c_out: out std_logic; + z_out: out std_logic; + + -- control signals + load_c: in std_logic; + load_z: in std_logic; + sel_c: in std_logic_vector(1 downto 0); + sel_z: in std_logic_vector(1 downto 0) + ); +end flaggroup; + +architecture rtl of flaggroup is + component flag + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic; + data_out: out std_logic + ); + end component; + + component multiplexer4 + generic ( + w : positive + ); + port ( + selector: in std_logic_vector(1 downto 0); + data_in_00: in std_logic_vector(w-1 downto 0); + data_in_01: in std_logic_vector(w-1 downto 0); + data_in_10: in std_logic_vector(w-1 downto 0); + data_in_11: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + for carry_flag: flag use entity work.flag(rtl); + for zero_flag: flag use entity work.flag(rtl); + + for carry_mux: multiplexer4 use entity work.multiplexer4(rtl); + for zero_mux: multiplexer4 use entity work.multiplexer4(rtl); + + signal mux_to_c: std_logic; + signal mux_to_z: std_logic; + + begin + carry_flag: flag port map ( + clk => clk, + load => load_c, + data_in => mux_to_c, + data_out => c_out + ); + + + zero_flag: flag port map ( + clk => clk, + load => load_z, + data_in => mux_to_z, + data_out => z_out + ); + + carry_mux: multiplexer4 + generic map + ( + w => 1 + ) + port map ( + selector => sel_c, + data_in_00(0) => c_in, + data_in_01(0) => '-', + data_in_10(0) => '0', + data_in_11(0) => '1', + data_out(0) => mux_to_c + ); + + + zero_mux: multiplexer4 + generic map + ( + w => 1 + ) + port map ( + selector => sel_z, + data_in_00(0) => z_in, + data_in_01(0) => '-', + data_in_10(0) => '0', + data_in_11(0) => '1', + data_out(0) => mux_to_z + ); + +end rtl; \ No newline at end of file Index: tags/arelease/cpu/groups/cpu.vhd =================================================================== --- tags/arelease/cpu/groups/cpu.vhd (nonexistent) +++ tags/arelease/cpu/groups/cpu.vhd (revision 10) @@ -0,0 +1,368 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: cpu +-- +-- PURPOSE: connects components of the +-- scalar unit and the vector unit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity cpu is + port( + clk: in std_logic; + reset: in std_logic; + + dbg_a: out std_logic_vector(31 downto 0); + dbg_x: out std_logic_vector(31 downto 0); + dbg_y: out std_logic_vector(31 downto 0); + dbg_ir: out std_logic_vector(31 downto 0); + dbg_ic: out std_logic_vector(31 downto 0); + dbg_carry: out std_logic; + dbg_zero: out std_logic; + dbg_ir_ready: out std_logic; + dbg_halted: out std_logic; + + mem_data_in: in std_logic_vector(31 downto 0); + mem_data_out: out std_logic_vector(31 downto 0); + mem_vdata_in: in vectordata_type; + mem_vdata_out: out vectordata_type; + mem_address: out std_logic_vector(31 downto 0); + mem_access: out std_logic_vector(2 downto 0); + mem_ready: in std_logic + ); +end cpu; + +architecture rtl of cpu is + component controlunit + port( + clk: in std_logic; + ir: in std_logic_vector(31 downto 0); + reset_cpu: in std_logic; + zero: in std_logic; + carry: in std_logic; + ready: in std_logic; + access_type: out std_logic_vector(2 downto 0); + c0: out std_logic; + c1: out std_logic; + cc2: out std_logic_vector(1 downto 0); + cc4: out std_logic_vector(1 downto 0); + cc5: out std_logic_vector(1 downto 0); + c6: out std_logic; + c7: out std_logic; + c8: out std_logic; + load_ir: out std_logic; + inc_ic: out std_logic; + load_ic: out std_logic; + load_c: out std_logic; + load_z: out std_logic; + ir_ready: out std_logic; + s_ready: out std_logic; + s_fetched: out std_logic; + v_ready: in std_logic; + v_fetched: in std_logic; + v_done: in std_logic; + halted: out std_logic + ); + end component; + + component aluinputgroup + port( + clk: in std_logic; + memory_in: in std_logic_vector(31 downto 0); + x_in: in std_logic_vector(31 downto 0); + y_in: in std_logic_vector(31 downto 0); + a_in: in std_logic_vector(31 downto 0); + ir_out: out std_logic_vector(31 downto 0); + k_out: out std_logic_vector(31 downto 0); + vector_out: out std_logic_vector(31 downto 0); + a_out: out std_logic_vector(31 downto 0); + b_out: out std_logic_vector(31 downto 0); + sel_a: in std_logic_vector(1 downto 0); + sel_b: in std_logic_vector(1 downto 0); + sel_source_a: in std_logic; + sel_source_b: in std_logic; + load_ir: in std_logic + ); + end component; + + component alu + port( + a_in: in std_logic_vector(31 downto 0); + b_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + aluop: in std_logic_vector(3 downto 0); + op_select: in std_logic; + zero_out: out std_logic; + carry_out: out std_logic; + alu_out: out std_logic_vector(31 downto 0) + ); + end component; + + component addressgroup + port( + clk: in std_logic; + address_in: in std_logic_vector(31 downto 0); + address_out: out std_logic_vector(31 downto 0); + ic_out: out std_logic_vector(31 downto 0); + sel_source: in std_logic; + inc: in std_logic; + load_ic: in std_logic; + reset_ic: in std_logic + ); + end component; + + component registergroup + port( + clk: in std_logic; + result_in: in std_logic_vector(31 downto 0); + vector_in: in std_logic_vector(31 downto 0); + ic_in: in std_logic_vector(31 downto 0); + enable_in: in std_logic; + x_out: out std_logic_vector(31 downto 0); + y_out: out std_logic_vector(31 downto 0); + a_out: out std_logic_vector(31 downto 0); + sel_source: in std_logic_vector(1 downto 0); + sel_dest: in std_logic_vector(1 downto 0) + ); + end component; + + component flaggroup + port( + clk: in std_logic; + c_in: in std_logic; + z_in: in std_logic; + c_out: out std_logic; + z_out: out std_logic; + load_c: in std_logic; + load_z: in std_logic; + sel_c: in std_logic_vector(1 downto 0); + sel_z: in std_logic_vector(1 downto 0) + ); + end component; + + component vector_controlunit + port( + clk: in std_logic; + ir: in std_logic_vector(31 downto 0); + load_r: out std_logic; + cc9: out std_logic_vector(1 downto 0); + c10: out std_logic; + c11: out std_logic; + c12: out std_logic; + cc13: out std_logic_vector(1 downto 0); + valu_go: out std_logic; + shuffle_go: out std_logic; + out_valid: in std_logic; + shuffle_valid: in std_logic; + ir_ready: in std_logic; + s_ready: in std_logic; + s_fetched: in std_logic; + v_ready: out std_logic; + v_fetched: out std_logic; + v_done: out std_logic + ); + end component; + + component vector_executionunit + port ( + clk: in std_logic; + memory_in: in vectordata_type; + scalar_in: in std_logic_vector(31 downto 0); + memory_out: out vectordata_type; + scalar_out: out std_logic_vector(31 downto 0); + out_valid: out std_logic; + shuffle_valid: out std_logic; + rrrr: in std_logic_vector(3 downto 0); + vvvv: in std_logic_vector(3 downto 0); + wwww: in std_logic_vector(3 downto 0); + k_in: in std_logic_vector(31 downto 0); + vn: in std_logic_vector(7 downto 0); + valuop: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + load_r: in std_logic; + cc9: in std_logic_vector(1 downto 0); + c10: in std_logic; + c11: in std_logic; + c12: in std_logic; + cc13: in std_logic_vector(1 downto 0); + valu_go: in std_logic; + shuffle_go: in std_logic + ); + end component; + + for controlunit_impl: controlunit use entity work.controlunit(rtl); + for aluinputgroup_impl: aluinputgroup use entity work.aluinputgroup(rtl); + for alu_impl: alu use entity work.alu(rtl); + for addressgroup_impl: addressgroup use entity work.addressgroup(rtl); + for registergroup_impl: registergroup use entity work.registergroup(rtl); + for flaggroup_impl: flaggroup use entity work.flaggroup(rtl); + for vector_controlunit_impl: vector_controlunit use entity work.vector_controlunit(rtl); + for vector_executionunit_impl: vector_executionunit use entity work.vector_executionunit(rtl); + + -- controlunit signals + signal ir: std_logic_vector(31 downto 0); + signal zero: std_logic; + signal carry: std_logic; + signal c0: std_logic; + signal c1: std_logic; + signal cc2: std_logic_vector(1 downto 0); + signal cc4: std_logic_vector(1 downto 0); + signal cc5: std_logic_vector(1 downto 0); + signal c6: std_logic; + signal c7: std_logic; + signal c8: std_logic; + signal load_ir: std_logic; + signal inc_ic: std_logic; + signal load_ic: std_logic; + signal load_c: std_logic; + signal load_z: std_logic; + signal ir_ready: std_logic; + signal s_ready: std_logic; + signal s_fetched: std_logic; + signal v_ready: std_logic; + signal v_fetched: std_logic; + signal v_done: std_logic; + + -- aluinputgroup + signal x: std_logic_vector(31 downto 0); + signal y: std_logic_vector(31 downto 0); + signal a: std_logic_vector(31 downto 0); + signal k_out: std_logic_vector(31 downto 0); + signal vector_out: std_logic_vector(31 downto 0); + signal alu_input_a: std_logic_vector(31 downto 0); + signal alu_input_b: std_logic_vector(31 downto 0); + + -- alu signals + signal aluop: std_logic_vector(3 downto 0) ; + signal zero_out: std_logic; + signal carry_out: std_logic; + signal alu_out: std_logic_vector(31 downto 0); + + -- address group signals + signal ic: std_logic_vector(31 downto 0); + + -- register group signals + signal vector_in: std_logic_vector(31 downto 0); + + -- signals from instruction + signal ss: std_logic_vector(1 downto 0); + signal dd: std_logic_vector(1 downto 0); + signal tt: std_logic_vector(1 downto 0); + + -- vector_controlunit signals + signal load_r: std_logic; + signal cc9: std_logic_vector(1 downto 0); + signal c10: std_logic; + signal c11: std_logic; + signal c12: std_logic; + signal cc13: std_logic_vector(1 downto 0); + signal valu_go: std_logic; + signal out_valid: std_logic; + signal shuffle_go: std_logic; + signal shuffle_valid: std_logic; + + -- vector_executionunit signals + signal rrrr: std_logic_vector(3 downto 0); + signal vvvv: std_logic_vector(3 downto 0); + signal wwww: std_logic_vector(3 downto 0); + signal vn: std_logic_vector(7 downto 0); + signal valuop: std_logic_vector(3 downto 0); + signal vwidth: std_logic_vector(1 downto 0); + +begin + + controlunit_impl: controlunit + port map ( + clk => clk, ir => ir, reset_cpu => reset, zero => zero, carry => carry, ready => mem_ready, + access_type => mem_access, c0 => c0, c1 => c1, cc2 => cc2, cc4 => cc4, cc5 => cc5, + c6 => c6, c7 => c7, c8 => c8, load_ir => load_ir, inc_ic => inc_ic, load_ic => load_ic, + load_c => load_c, load_z => load_z, ir_ready => ir_ready, s_ready => + s_ready, s_fetched => s_fetched,v_ready => v_ready, v_fetched => v_fetched, v_done => v_done, + halted => dbg_halted + ); + + aluinputgroup_impl: aluinputgroup + port map ( + clk => clk, memory_in => mem_data_in, x_in => x, y_in => y, a_in => a, ir_out => ir, k_out => k_out, + vector_out => vector_out, a_out => alu_input_a, b_out => alu_input_b, sel_a => ss, sel_b => tt, + sel_source_a => c8, sel_source_b => c0, load_ir => load_ir + ); + + alu_impl: alu + port map ( + a_in => alu_input_a, b_in => alu_input_b, carry_in => carry, aluop => aluop, + op_select => c7, carry_out => carry_out, zero_out => zero_out, alu_out => alu_out + ); + + addressgroup_impl: addressgroup + port map ( + clk => clk, address_in => alu_out, address_out => mem_address, ic_out => ic, sel_source => c1, + inc => inc_ic, load_ic => load_ic, reset_ic => reset + ); + + registergroup_impl: registergroup + port map ( + clk => clk, result_in => alu_out, vector_in => vector_in, + ic_in => ic, enable_in => c6, x_out => x, y_out => y, a_out => a, + sel_source => cc2, sel_dest => dd + ); + + flaggroup_impl: flaggroup + port map ( + clk => clk, c_in => carry_out, z_in => zero_out, c_out => carry, + z_out => zero, load_c => load_c, load_z => load_z, sel_c => cc5, sel_z => cc4 + ); + + vector_controlunit_impl: vector_controlunit + port map ( + clk => clk, ir => ir, load_r => load_r, cc9 => cc9, c10 => c10, c11 => c11, + c12 => c12, cc13 => cc13, valu_go => valu_go, shuffle_go => shuffle_go, out_valid => out_valid, + shuffle_valid => shuffle_valid, ir_ready => ir_ready, s_ready => s_ready, s_fetched => s_fetched, + v_ready => v_ready, v_fetched => v_fetched, v_done => v_done + ); + + vector_executionunit_impl: vector_executionunit + port map ( + clk => clk, memory_in => mem_vdata_in, scalar_in => vector_out, memory_out => mem_vdata_out, + scalar_out => vector_in, out_valid => out_valid, shuffle_valid => shuffle_valid, rrrr => rrrr, + vvvv => vvvv, wwww => wwww, k_in => k_out, vn => vn, valuop => valuop, vwidth => vwidth, + load_r => load_r, cc9 => cc9, c10 => c10, c11 => c11, c12 => c12, cc13 => cc13, valu_go => valu_go, + shuffle_go => shuffle_go + ); + + -- from ir derived signals + dd <= ir (25 downto 24); + ss <= ir (23 downto 22); + tt <= ir (21 downto 20); + aluop <= ir (29 downto 26); + rrrr <= ir (11 downto 8); + vvvv <= ir (7 downto 4); + wwww <= ir (3 downto 0); + vn <= ir (27 downto 20); + valuop <= ir (15 downto 12); + vwidth <= ir (17 downto 16); + + -- memory interfaces signals + mem_data_out <= a; + + -- debugging signals + dbg_a <= a; + dbg_x <= x; + dbg_y <= y; + dbg_ir <= ir; + dbg_ic <= ic; + dbg_carry <= carry; + dbg_zero <= zero; + dbg_ir_ready <= ir_ready; + +end; \ No newline at end of file Index: tags/arelease/cpu/groups/aluinputgroup.vhd =================================================================== --- tags/arelease/cpu/groups/aluinputgroup.vhd (nonexistent) +++ tags/arelease/cpu/groups/aluinputgroup.vhd (revision 10) @@ -0,0 +1,156 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: aluinputgroup +-- +-- PURPOSE: consists of and connects components +-- used to switch inputs for the scalar +-- alu +-- also includes instruction register +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity aluinputgroup is + port( -- clock + clk: in std_logic; + + -- data inputs + memory_in: in std_logic_vector(31 downto 0); -- data from ram + x_in: in std_logic_vector(31 downto 0); + y_in: in std_logic_vector(31 downto 0); + a_in: in std_logic_vector(31 downto 0); + + -- data outputs + ir_out: out std_logic_vector(31 downto 0); + k_out: out std_logic_vector(31 downto 0); -- k for vector unit + vector_out: out std_logic_vector(31 downto 0); -- data for vector unit + a_out: out std_logic_vector(31 downto 0); + b_out: out std_logic_vector(31 downto 0); + + -- control signals + sel_a: in std_logic_vector(1 downto 0); + sel_b: in std_logic_vector(1 downto 0); + sel_source_a: in std_logic; -- c8 + sel_source_b: in std_logic; -- c0 + load_ir: in std_logic + ); +end aluinputgroup; + +architecture rtl of aluinputgroup is + component dataregister + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + component multiplexer4 + generic ( + w : positive + ); + port ( + selector: in std_logic_vector(1 downto 0); + data_in_00: in std_logic_vector(w-1 downto 0); + data_in_01: in std_logic_vector(w-1 downto 0); + data_in_10: in std_logic_vector(w-1 downto 0); + data_in_11: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + component multiplexer2 + generic ( + w : positive + ); + port ( + selector: in std_logic; + data_in_0: in std_logic_vector(w-1 downto 0); + data_in_1: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + for ir: dataregister use entity work.dataregister(rtl); + for mux_a: multiplexer4 use entity work.multiplexer4(rtl); + for mux_b: multiplexer4 use entity work.multiplexer4(rtl); + for mux_source_b: multiplexer2 use entity work.multiplexer2(rtl); + for mux_source_a: multiplexer2 use entity work.multiplexer2(rtl); + + signal instruction: std_logic_vector(31 downto 0); + signal n: std_logic_vector(31 downto 0); + signal mux_a_to_source: std_logic_vector(31 downto 0); + signal mux_b_to_source: std_logic_vector(31 downto 0); + + begin + ir: dataregister + port map ( + clk => clk, + load => load_ir, + data_in => memory_in, + data_out => instruction + ); + + mux_a: multiplexer4 + generic map ( + w => 32 + ) + port map ( + selector => sel_a, + data_in_00 => "00000000000000000000000000000000", + data_in_01 => a_in, + data_in_10 => x_in, + data_in_11 => y_in, + data_out => mux_a_to_source + ); + + mux_b: multiplexer4 + generic map ( + w => 32 + ) + port map ( + selector => sel_b, + data_in_00 => n, + data_in_01 => a_in, + data_in_10 => x_in, + data_in_11 => y_in, + data_out => mux_b_to_source + ); + + mux_source_a: multiplexer2 + generic map ( + w => 32 + ) + port map ( + selector => sel_source_a, + data_in_0 => mux_a_to_source, + data_in_1 => "00000000000000000000000000000000", + data_out => a_out + ); + + + mux_source_b: multiplexer2 + generic map ( + w => 32 + ) + port map ( + selector => sel_source_b, + data_in_0 => mux_b_to_source, + data_in_1 => memory_in, + data_out => b_out + ); + + + n(15 downto 0) <= instruction(15 downto 0); + n(31 downto 16) <= "0000000000000000"; + k_out <= mux_b_to_source; + vector_out <= mux_a_to_source; + ir_out <= instruction; + +end rtl; \ No newline at end of file Index: tags/arelease/cpu/units/vector_controlunit.vhd =================================================================== --- tags/arelease/cpu/units/vector_controlunit.vhd (nonexistent) +++ tags/arelease/cpu/units/vector_controlunit.vhd (revision 10) @@ -0,0 +1,274 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: vector_controlunit +-- +-- PURPOSE: controlunit for vector unit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +use work.cfg.all; + +entity vector_controlunit is + port( + -- clock + clk: in std_logic; -- clock signal + + -- instruction in + ir: in std_logic_vector(31 downto 0); -- instruction + + -- control signals out + load_r: out std_logic; + cc9: out std_logic_vector(1 downto 0); + c10: out std_logic; + c11: out std_logic; + c12: out std_logic; + cc13: out std_logic_vector(1 downto 0); + valu_go: out std_logic; + shuffle_go: out std_logic; + + -- control signals in + out_valid: in std_logic; + shuffle_valid: in std_logic; + + -- communication with scalar unit + ir_ready: in std_logic; -- next instruction has been loaded into ir + s_ready: in std_logic; -- data from scalar unit or mi is ready + s_fetched: in std_logic; -- signal for vector unit to continue + + v_ready: out std_logic; -- data for scalar unit or mi is ready + v_fetched: out std_logic; -- signal for scalar unit to continue + v_done: out std_logic -- vector unit completed command + ); +end vector_controlunit; + +architecture rtl of vector_controlunit is + type statetype is (wfi, decode_wait, vmovrv, vmovrrn, vmovrnv, valu1, valu2, valu3, vld, vtos, + movrts, mova, shuffle1, shuffle2, shuffle3, vmol, vmor); + + signal state : statetype := wfi; + signal nextstate : statetype := wfi; + +begin + + -- state register + process + begin + wait until clk='1' and clk'event; + state <= nextstate; + + end process; + + -- state transitions + process (state, ir, ir_ready, s_ready, s_fetched, out_valid, shuffle_valid) + begin + -- avoid latches + load_r <= '0'; + cc9 <= "00"; + c10 <= '0'; + c11 <= '0'; + c12 <= '0'; + cc13 <= "00"; + v_ready <= '0'; + v_fetched <= '0'; + v_done <= '0'; + valu_go <= '0'; + shuffle_go <= '0'; + + nextstate <= wfi; + + case state is + + -- WAIT FOR INSTRUCTION STATE -- + when wfi => + if ir_ready = '1' then + nextstate <= decode_wait; + else + v_done <= '1'; + nextstate <= wfi; + end if; + + -- DECODE AND WAIT STATE -- + when decode_wait => + case ir(19 downto 18) is + when "00" => + if ir(17) = '0' then -- vnop + nextstate <= wfi; + else + case ir(15 downto 12) is + when "0001" => -- vmov r,v + nextstate <= vmovrv; + + when "0010" => -- vmov r, R + nextstate <= vmovrrn; + + when "0011" => -- vmov R, v + nextstate <= vmovrnv; + + when "1000" => -- vmol r,v + nextstate <= vmol; + + when "1100" => -- vmor r,v + nextstate <= vmor; + + when others => -- error => ignore command + nextstate <= wfi; + end case; + end if; + + when "01" => -- valu + nextstate <= valu1; + + when "10" => -- vld/vst/move + case ir(15 downto 12) is + when "0010" => -- vld + if s_ready = '1' then + nextstate <= vld; + else + nextstate <= decode_wait; + end if; + + when "0011" | "0101" => -- vst, mov d, v(t) + nextstate <= vtos; + + when "0100" => -- mov r(t), s + if s_ready = '1' then + nextstate <= movrts; + else + nextstate <= decode_wait; + end if; + + when "0110" => -- mova + if s_ready = '1' then + nextstate <= mova; + else + nextstate <= decode_wait; + end if; + + when others => -- error => ignore command + nextstate <= wfi; + end case; + + when "11" => -- shuffle + if use_shuffle then + nextstate <= shuffle1; + else + nextstate <= wfi; + end if; + when others => -- error + nextstate <= wfi; + end case; + + -- VMOL R,V STATE -- + when vmol => + cc13 <= "10"; + cc9 <= "11"; + load_r <= '1'; + nextstate <= wfi; + + -- VMOR R,V STATE -- + when vmor => + cc13 <= "11"; + cc9 <= "11"; + load_r <= '1'; + nextstate <= wfi; + + -- VMOV R,V STATE -- + when vmovrv => + cc13 <= "01"; + cc9 <= "11"; + load_r <= '1'; + nextstate <= wfi; + + -- VMOV R,R STATE -- + when vmovrrn => + cc13 <= "01"; + cc9 <= "11"; + c11 <= '1'; + load_r <= '1'; + nextstate <= wfi; + + -- VMOV R,V STATE -- + when vmovrnv => + cc13 <= "01"; + cc9 <= "11"; + c10 <= '1'; + load_r <= '1'; + nextstate <= wfi; + + -- VALU COMMAND STATE -- + when valu1 => + valu_go <= '1'; + nextstate <= valu2; + + when valu2 => + if out_valid = '0' then + nextstate <= valu2; + else + nextstate <= valu3; + end if; + + when valu3 => + load_r <= '1'; + nextstate <= wfi; + + -- VLD STATE -- + when vld => + cc9 <= "10"; + load_r <= '1'; + v_fetched <= '1'; + nextstate <= wfi; + + -- VECTOR TO SCALAR STATE -- + when vtos => + v_ready <= '1'; + + if s_fetched = '1' then + nextstate <= wfi; + else + nextstate <= vtos; + end if; + + -- MOV R(T),S STATE -- + when movrts => + cc9 <= "01"; + c12 <= '1'; + load_r <= '1'; + v_fetched <= '1'; + nextstate <= wfi; + + -- MOVA STATE -- + when mova => + cc9 <= "01"; + load_r <= '1'; + v_fetched <= '1'; + nextstate <= wfi; + + -- SHUFFLE STATES + when shuffle1 => + shuffle_go <= '1'; + nextstate <= shuffle2; + + when shuffle2 => + if shuffle_valid = '0' then + nextstate <= shuffle2; + else + nextstate <= shuffle3; + end if; + + when shuffle3 => + cc9 <= "11"; + load_r <= '1'; + nextstate <= wfi; + + end case; + end process; +end rtl; + Index: tags/arelease/cpu/units/sram.vhd =================================================================== --- tags/arelease/cpu/units/sram.vhd (nonexistent) +++ tags/arelease/cpu/units/sram.vhd (revision 10) @@ -0,0 +1,47 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: sram +-- +-- PURPOSE: sram memory +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; + +entity sram is + port ( + clk : in std_logic; + we : in std_logic; + en : in std_logic; + addr : in std_logic_vector(31 downto 0); + di : in std_logic_vector(31 downto 0); + do : out std_logic_vector(31 downto 0) + ); +end sram; + +architecture rtl of sram is + type memory_type is array(0 to sram_size) of std_logic_vector(31 downto 0); + signal memory : memory_type; +begin + process (clk) + begin + if clk'event and clk = '1' then + if en = '1' then + if we = '1' then + memory(conv_integer(addr)) <= di; + do <= di; + else + do <= memory(conv_integer(addr)); + end if; + end if; + end if; + end process; +end; Index: tags/arelease/cpu/units/vector_register.vhd =================================================================== --- tags/arelease/cpu/units/vector_register.vhd (nonexistent) +++ tags/arelease/cpu/units/vector_register.vhd (revision 10) @@ -0,0 +1,68 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: vector_register +-- +-- PURPOSE: 32 bit register file for vector_slice +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity vector_register is + generic ( + n : integer range 1 to 256; + slicenr : natural + ); + + port ( + -- clock + clk: in std_logic; + + -- data inputs + r_in: in std_logic_vector(31 downto 0); + + -- data outputs + v_out: out std_logic_vector(31 downto 0); + w_out: out std_logic_vector(31 downto 0); + + -- control signals + load_r: in std_logic; + load_select: in std_logic; + k_in: in std_logic_vector(31 downto 0); + select_v: in std_logic_vector(7 downto 0); + select_w: in std_logic_vector(3 downto 0); + select_r: in std_logic_vector(7 downto 0) + ); + +end vector_register; + +architecture rtl of vector_register is + type regfile_type is array(0 to n-1) of std_logic_vector(31 downto 0); + signal regfile : regfile_type := (others => (others => '0')); +begin + process + begin + wait until clk='1' and clk'event; + + if (load_r = '1' and load_select /= '1') or (load_r = '1' and load_select = '1' + and k_in = slicenr) then + regfile(conv_integer(select_r)) <= r_in; + end if; + + v_out <= regfile(conv_integer(select_v)); + w_out <= regfile(conv_integer(select_w)); + end process; + + +end rtl; + Index: tags/arelease/cpu/units/valu_controlunit.vhd =================================================================== --- tags/arelease/cpu/units/valu_controlunit.vhd (nonexistent) +++ tags/arelease/cpu/units/valu_controlunit.vhd (revision 10) @@ -0,0 +1,220 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: valu_controlunit +-- +-- PURPOSE: common controlunit of the +-- vector alus +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + + +entity valu_controlunit is + port( + clk: in std_logic; + valu_go: in std_logic; + valuop: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + source_sel: out std_logic_vector(1 downto 0); + carry_sel: out std_logic_vector(1 downto 0); + mult_source_sel: out std_logic_vector(1 downto 0); + mult_dest_sel: out std_logic_vector(1 downto 0); + reg_input_sel: out std_logic; + load_lsr: out std_logic; + load_other: out std_logic; + out_valid: out std_logic + ); +end; + +architecture rtl of valu_controlunit is + type statetype is (waiting, vlsr, vlsr64, vother, vother64, vmult8, vmult16); + signal state : statetype := waiting; + signal nextstate : statetype := waiting; + + signal counter: unsigned(1 downto 0) := "00"; + signal inc, reset: std_logic; +begin + + -- counter + process + variable x : unsigned(1 downto 0); + begin + wait until clk ='1' and clk'event; + if reset = '1' then + counter <= (others => '0'); + else + if inc = '1' then + x := unsigned(counter); + counter <= counter + 1; + end if; + end if; + end process; + + + -- state register + process + begin + wait until clk ='1' and clk'event; + state <= nextstate; + end process; + + -- state transitions + process (state, valu_go, valuop, vwidth, counter) + variable lsr_result: unsigned(8 downto 0); + begin + -- avoid latches + out_valid <= '0'; + + reset <= '0'; + inc <= '0'; + + load_lsr <= '0'; + load_other <= '0'; + + mult_source_sel <= "00"; + mult_dest_sel <= "00"; + reg_input_sel <= '0'; + + case state is + -- waiting for go command from vector controlunit + when waiting => + out_valid <= '1'; + reset <= '1'; + nextstate <= waiting; + + if valu_go = '1' then + case valuop is + when "1110" => + nextstate <= vlsr; + + when "1011" => + if vwidth(0) = '0' then + nextstate <= vmult8; + else + nextstate <= vmult16; + end if; + + when others => + nextstate <= vother; + end case; + else + nextstate <= waiting; + end if; + + -- normal alu commands + when vother => + inc <= '1'; + load_other <= '1'; + + if counter = 3 then + if vwidth = "11" then + nextstate <= vother64; + else + nextstate <= waiting; + end if; + else + nextstate <= vother; + end if; + + -- normal alu commands 64 bit + when vother64 => + inc <= '1'; + load_other <= '1'; + + if counter = 3 then + nextstate <= waiting; + else + nextstate <= vother64; + end if; + + -- vector shift right command + when vlsr => + inc <= '1'; + load_lsr <= '1'; + + if counter = 3 then + if vwidth = "11" then + nextstate <= vlsr64; + else + nextstate <= waiting; + end if; + else + nextstate <= vlsr; + end if; + + -- vector shift right command 64 bit + when vlsr64 => + inc <= '1'; + load_lsr <= '1'; + + if counter = 3 then + nextstate <= waiting; + else + nextstate <= vlsr64; + end if; + + -- multiplication with 8 bit + when vmult8 => + inc <= '1'; + load_other <= '1'; + + reg_input_sel <= '1'; + + case counter is + when "00" => + mult_source_sel <= "00"; + mult_dest_sel <= "00"; + nextstate <= vmult8; + when "01" => + mult_source_sel <= "00"; + mult_dest_sel <= "01"; + nextstate <= vmult8; + when "10" => + mult_source_sel <= "01"; + mult_dest_sel <= "00"; + nextstate <= vmult8; + when "11" => + mult_source_sel <= "01"; + mult_dest_sel <= "01"; + nextstate <= waiting; + when others => + nextstate <= waiting; + end case; + + -- multiplication with 16 bit + when vmult16 => + inc <= '1'; + load_other <= '1'; + + mult_source_sel <= "10"; + mult_dest_sel <= std_logic_vector(counter); + reg_input_sel <= '1'; + + if counter = 3 then + nextstate <= waiting; + else + nextstate <= vmult16; + end if; + end case; + end process; + + source_sel <= "00" when ( (counter = 0 and valuop /= "1110") or (counter = 3 and valuop = "1110") ) else + "01" when ( (counter = 1 and valuop /= "1110") or (counter = 2 and valuop = "1110") ) else + "10" when ( (counter = 2 and valuop /= "1110") or (counter = 1 and valuop = "1110") ) else + "11"; + + + carry_sel <= "00" when (vwidth = "11" and counter = 0) else -- 64 bit + "01" when (vwidth(1) = '1' and counter /= 0) else -- 32 and 64 bit + "01" when (vwidth = "01" and (counter = 1 or counter = 3)) else -- 16 bit + "10"; -- 8 bit + + +end rtl; Index: tags/arelease/cpu/units/vector_alu_32.vhd =================================================================== --- tags/arelease/cpu/units/vector_alu_32.vhd (nonexistent) +++ tags/arelease/cpu/units/vector_alu_32.vhd (revision 10) @@ -0,0 +1,146 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: vector_alu_32 +-- +-- PURPOSE: 32 bit vector alu +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +use work.cfg.all; + +entity vector_alu_32 is + port( + -- clock + clk: in std_logic; + + -- data in + v_in: in std_logic_vector(31 downto 0); + w_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + rshift_in: in std_logic; + + -- data out + carry_out: out std_logic; + valu_out: out std_logic_vector(31 downto 0); + + -- control signals + valuop: in std_logic_vector(3 downto 0); + source_sel: in std_logic_vector(1 downto 0); + carry_sel: in std_logic_vector(1 downto 0); + mult_source_sel: in std_logic_vector(1 downto 0); -- * + mult_dest_sel: in std_logic_vector(1 downto 0); -- * + reg_input_sel: in std_logic; -- * + load_lsr: in std_logic; + load_other: in std_logic + ); +end; + + +architecture rtl of vector_alu_32 is + + signal carry, rshift: std_logic; + + signal left : unsigned(8 downto 0); -- left operand + signal right : unsigned(8 downto 0); -- right operand + signal valu_res: unsigned(8 downto 0); -- result (mult_res8 or valu_res) + + signal mult_right: unsigned(15 downto 0); -- right multiplication operand + signal mult_left: unsigned(15 downto 0); -- left multiplication operand + signal mult_res32: unsigned(31 downto 0); -- multiplication result + signal mult_res8: unsigned(7 downto 0); -- shift value for result shift register (multiplication) + + signal output: unsigned(32 downto 0); -- result shift register + signal input : unsigned (8 downto 0); -- shift value for result shift register (other operations) + + +begin + carry <= carry_in when (carry_sel = "00") else + output(32) when (carry_sel = "01") else + '0'; + + rshift <= rshift_in when (carry_sel = "00") else + output(32) when (carry_sel = "01") else + '0'; + + left <= unsigned('0' & v_in(7 downto 0)) when (source_sel) = "00" else + unsigned('0' & v_in(15 downto 8)) when (source_sel) = "01" else + unsigned('0' & v_in(23 downto 16)) when (source_sel) = "10" else + unsigned('0' & v_in(31 downto 24)); + + right <= unsigned('0' & w_in(7 downto 0)) when (source_sel) = "00" else + unsigned('0' & w_in(15 downto 8)) when (source_sel) = "01" else + unsigned('0' & w_in(23 downto 16)) when (source_sel) = "10" else + unsigned('0' & w_in(31 downto 24)); + + -- execute all other operations + valu_res <= left + right + carry when (valuop = "0000") else + left - right - carry when (valuop = "0010") else + left(7 downto 0) & carry when (valuop = "1100") else + left(0) & rshift & left(7 downto 1) when (valuop = "1110") else + unsigned( std_logic_vector(left) and std_logic_vector(right)) when (valuop = "1000") else + unsigned( std_logic_vector(left) or std_logic_vector(right)) when (valuop = "1001") else + unsigned( std_logic_vector(left) xor std_logic_vector(right)); + + mult_gen: if use_vector_mult generate + -- operands for multiplication + mult_left <= unsigned("00000000" & v_in(7 downto 0)) when mult_source_sel = "00" else + unsigned("00000000" & v_in(23 downto 16)) when mult_source_sel = "01" else + unsigned(v_in(15 downto 0)); + + mult_right <= unsigned("00000000" & w_in(7 downto 0)) when mult_source_sel = "00" else + unsigned("00000000" & w_in(23 downto 16)) when mult_source_sel = "01" else + unsigned(w_in(15 downto 0)); + + -- execute multiplication + mult_res32 <= mult_left * mult_right; + + mult_res8 <= mult_res32(7 downto 0) when mult_dest_sel = "00" else + mult_res32(15 downto 8) when mult_dest_sel = "01" else + mult_res32(23 downto 16) when mult_dest_sel = "10" else + mult_res32(31 downto 24); + + + end generate; + + not_mult_gen: if not use_vector_mult generate + mult_res8 <= "00000000"; + end generate; + + -- use result from other operation or multiplication? + input <= valu_res when reg_input_sel = '0' else "0" & mult_res8; + + -- output register + process + begin + wait until clk ='1' and clk'event; + if load_other = '1' then + -- shift from right to left + output(32 downto 24) <= input(8 downto 0); + output(23 downto 0) <= output(31 downto 8); + else + if load_lsr = '1' then + -- shift from left to right + output(7 downto 0) <= input(7 downto 0); + output(32) <= input(8); + output(31 downto 8) <= output(23 downto 0); + else + output <= output; + end if; + end if; + end process; + + valu_out <= std_logic_vector(output(31 downto 0)); + carry_out <= output(32); + +end rtl; + + + Index: tags/arelease/cpu/units/flag.vhd =================================================================== --- tags/arelease/cpu/units/flag.vhd (nonexistent) +++ tags/arelease/cpu/units/flag.vhd (revision 10) @@ -0,0 +1,43 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: flag +-- +-- PURPOSE: one bit flag for status register +-- carry or zero +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity flag is + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic; + data_out: out std_logic + ); +end flag; + +architecture rtl of flag is + signal q: std_logic; +begin + process + begin + wait until clk='1' and clk'event; + + if load = '1' then + q <= data_in; + else + q <= q; + end if; + + end process; + + data_out <= q; +end rtl; + Index: tags/arelease/cpu/units/dataregister.vhd =================================================================== --- tags/arelease/cpu/units/dataregister.vhd (nonexistent) +++ tags/arelease/cpu/units/dataregister.vhd (revision 10) @@ -0,0 +1,41 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: dataregister +-- +-- PURPOSE: single dataregister of scalar unit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity dataregister is + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); +end dataregister; + +architecture rtl of dataregister is + signal data_out_buffer: unsigned(31 downto 0); +begin + process + begin + wait until clk='1' and clk'event; + + if load = '1' then + data_out_buffer <= unsigned(data_in); + else + data_out_buffer <= data_out_buffer; + end if; + end process; + + data_out <= std_logic_vector(data_out_buffer); +end rtl; + Index: tags/arelease/cpu/units/selectunit.vhd =================================================================== --- tags/arelease/cpu/units/selectunit.vhd (nonexistent) +++ tags/arelease/cpu/units/selectunit.vhd (revision 10) @@ -0,0 +1,35 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: selectunit +-- +-- PURPOSE: selects one word out of a vector +-- register +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity selectunit is + port ( + data_in : in vectordata_type; + k_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); +end selectunit; + +architecture rtl of selectunit is + signal index: integer range 0 to k-1; +begin + index <= conv_integer(k_in) when (k_in < k) else 0; + data_out <= data_in(index); +end rtl; \ No newline at end of file Index: tags/arelease/cpu/units/controlunit.vhd =================================================================== --- tags/arelease/cpu/units/controlunit.vhd (nonexistent) +++ tags/arelease/cpu/units/controlunit.vhd (revision 10) @@ -0,0 +1,435 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: controlunit +-- +-- PURPOSE: controlunit of scalar unit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity controlunit is + port( + -- clock + clk: in std_logic; -- clock signal + + -- instruction in + ir: in std_logic_vector(31 downto 0); -- instruction + + -- control signals in + reset_cpu: in std_logic; -- reset signal + zero: in std_logic; -- zero flag + carry: in std_logic; -- carry flag + ready: in std_logic; -- memory interface ready signal + + -- control signals out + access_type: out std_logic_vector(2 downto 0); -- memory interface access type (we, oe, cs) + c0: out std_logic; -- c0 signal + c1: out std_logic; -- c1 signal + cc2: out std_logic_vector(1 downto 0); -- cc2 signal + --c3: out std_logic; -- c3 signal => obsolete + cc4: out std_logic_vector(1 downto 0); -- cc4 signal + cc5: out std_logic_vector(1 downto 0); -- cc5 signal + c6: out std_logic; -- c6 signal + c7: out std_logic; -- c7 signal + c8: out std_logic; -- c7 signal + load_ir: out std_logic; -- instruction register load signal + inc_ic: out std_logic; -- instruction counter increment signal + load_ic: out std_logic; -- instruction counter load signal + load_c: out std_logic; -- carry flag load signal + load_z: out std_logic; -- zero flag load signal + + -- communication with vecor unit + ir_ready: out std_logic; -- next instruction has been loaded into ir + s_ready: out std_logic; -- data from scalar unit or mi is ready + s_fetched: out std_logic; -- signal for vector unit to continue + + v_ready: in std_logic; -- data for scalar unit or mi is ready + v_fetched: in std_logic; -- signal for scalar unit to continue + v_done: in std_logic; -- vector unit completed command + + halted: out std_logic -- enabled when cpu is in halt state + ); +end controlunit; + +architecture rtl of controlunit is + type statetype is (if1, if2, decode_wait, ld1, ld2, vld1, vld2, vld3, vld4, + st1, st2, vst1, vst2, vst3, smv1, smv2, vms1, vms2, nop, jal, jcc, alu, flag, sync, halt, + mova1, mova2, reset); + + signal state : statetype := halt; + signal nextstate : statetype := halt; + +begin + + -- state register + process + begin + wait until clk='1' and clk'event; + state <= nextstate; + + end process; + + -- state transitions + process (state, ready, reset_cpu, ir, carry, zero, v_ready, v_fetched, v_done) + begin + -- avoid latches + access_type <= "000"; + c0 <= '0'; + c1 <= '0'; + cc2 <= "00"; + cc4 <= "00"; + cc5 <= "00"; + c6 <= '0'; + c7 <= '0'; + c8 <= '0'; + load_ir <= '0'; + inc_ic <= '0'; + load_ic <= '0'; + load_c <= '0'; + load_z <= '0'; + ir_ready <= '0'; + s_ready <= '0'; + s_fetched <= '0'; + nextstate <= reset; + halted <= '0'; + + if reset_cpu = '1' then + nextstate <= reset; + else + case state is + -- RESET STATE -- + when reset => + cc4 <= "10"; + cc5 <= "10"; + load_c <= '1'; + load_z <= '1'; + nextstate <= if1; + + -- INSTRUCTION FETCH STATE 1 -- + when if1 => + access_type <= "010"; + nextstate <= if2; + + -- INSTRUCTION FETCH STATE 2 -- + when if2 => + access_type <= "010"; + ir_ready <= '1'; + load_ir <= '1'; + + if ready = '0' then + nextstate <= if2; + else + nextstate <= decode_wait; + end if; + + -- DECODE AND WAIT STATE -- + when decode_wait => + if ir(31 downto 28) = "1000" then -- ld + if ready = '1' then + nextstate <= ld1; + else + nextstate <= decode_wait; + end if; + + elsif ir(31 downto 28) = "1001" then -- vld + if ready = '1' then + nextstate <= vld1; + else + nextstate <= decode_wait; + end if; + + elsif ir(31 downto 28) = "1010" then -- store + if ready = '1' then + nextstate <= st1; + else + nextstate <= decode_wait; + end if; + + elsif ir(31 downto 26) = "101100" then -- vst + if ready = '1' and v_ready = '1' then + nextstate <= vst1; + else + nextstate <= decode_wait; + end if; + + elsif ir(31 downto 26) = "101101" then -- mova + nextstate <= mova1; + + elsif ir(31 downto 26) = "101110" then -- mov r(t), s + nextstate <= smv1; + + elsif ir(31 downto 26) = "101111" then -- mov d, v(t) + nextstate <= vms1; + + else + case ir(31 downto 30) is + when "00" => + if ir(29) = '0' then -- nop + nextstate <= nop; + + elsif ir(29 downto 27) = "101" then -- halt + report "HALT"; + nextstate <= halt; + + elsif ir(29 downto 26) = "1000" then -- jmp, jal + nextstate <= jal; + + elsif ir(29 downto 28) = "11" then -- jcc + nextstate <= jcc; + end if; + + when "01" => -- alu cmd + nextstate <= alu; + + when "11" => -- set/clear flags + nextstate <= flag; + + when others => -- error + nextstate <= halt; + end case; + end if; + + + -- LOAD STATE 1 -- + when ld1 => + access_type <= "010"; + c1 <= '1'; + c7 <= '1'; + nextstate <= ld2; + + -- LOAD STATE 2 -- + when ld2 => + access_type <= "010"; + report "LD"; + c0 <= '1'; + c6 <= '1'; + c7 <= '1'; + c8 <= '1'; + load_z <= '1'; + inc_ic <= '1'; + + if ready = '0' then + nextstate <= ld2; + else + nextstate <= sync; + end if; + + + -- VECTOR LOAD STATE 1 -- + when vld1 => + access_type <= "011"; + c1 <= '1'; + c7 <= '1'; + + if ready = '1' then + nextstate <= vld1; + else + nextstate <= vld2; + end if; + + -- VECTOR LOAD STATE 2 -- + when vld2 => + access_type <= "011"; + c1 <= '1'; + c7 <= '1'; + + if ready = '1' then + nextstate <= vld3; + else + nextstate <= vld2; + end if; + + -- VECTOR LOAD STATE 3 -- + when vld3 => + access_type <= "011"; + c1 <= '1'; + c7 <= '1'; + s_ready <= '1'; + + if v_fetched = '1' then + nextstate <= vld4; + else + nextstate <= vld3; + end if; + + -- VECTOR LOAD STATE 4 -- + when vld4 => + report "VLD"; + inc_ic <= '1'; + nextstate <= sync; + + -- STORE STATE 1 -- + when st1 => + access_type <= "100"; + c1 <= '1'; + c7 <= '1'; + inc_ic <= '1'; + + nextstate <= st2; + + -- STORE STATE 2 -- + when st2 => + access_type <= "100"; + c1 <= '1'; + c7 <= '1'; + + if ready = '0' then + nextstate <= st2; + else + nextstate <= sync; + end if; + + + -- VECTOR STORE STATE 1 -- + when vst1 => + access_type <= "101"; + c1 <= '1'; + c7 <= '1'; + + if ready = '1' then + nextstate <= vst1; + else + nextstate <= vst2; + end if; + + -- VECTOR STORE STATE 2 -- + when vst2 => + access_type <= "101"; + c1 <= '1'; + c7 <= '1'; + + if ready = '1' then + nextstate <= vst3; + else + nextstate <= vst2; + end if; + + -- VECTOR STORE STATE 3 -- + when vst3 => + report "VST"; + s_fetched <= '1'; + inc_ic <= '1'; + nextstate <= sync; + + -- SCALAR MOVE TO VECTOR STATE 1 -- + when smv1 => + s_ready <= '1'; + + if v_fetched = '1' then + nextstate <= smv2; + else + nextstate <= smv1; + end if; + + -- SCALAR MOVE TO VECTOR STATE 2 -- + when smv2 => + report "MOV R(T), S"; + inc_ic <= '1'; + nextstate <= sync; + + -- MOVA STATE 1 -- + when mova1 => + s_ready <= '1'; + + if v_fetched = '1' then + nextstate <= mova2; + else + nextstate <= mova1; + end if; + + -- MOVA STATE 2 -- + when mova2 => + report "MOVA"; + inc_ic <= '1'; + nextstate <= sync; + + -- VECTOR MOVE TO SCALAR STATE -- + when vms1 => + if v_ready = '1' then + nextstate <= vms2; + else + nextstate <= vms1; + end if; + + -- VECTOR MOVE TO SCALAR STATE 2 -- + when vms2 => + report "MOV D, V(T)"; + cc2 <= "10"; + c6 <= '1'; + s_fetched <= '1'; + inc_ic <= '1'; + nextstate <= sync; + + -- NOP STATE -- + when nop => + report "NOP"; + inc_ic <= '1'; + nextstate <= sync; + + -- JUMP AND LINK STATE + when jal => + report "JMP, JAL"; + c7 <= '1'; + load_ic <= '1'; + cc2 <= "01"; + c6 <= '1'; + nextstate <= sync; + + -- JUMP CONDITIONAL STATE + when jcc => + report "JCC"; + if (ir(27) = '0' and ir(26) = carry) + or (ir(27) = '1' and ir(26) = zero) then + c7 <= '1'; + load_ic <= '1'; + else + inc_ic <= '1'; + end if; + + nextstate <= sync; + + -- ALU COMMAND STATE -- + when alu => + report "ALU COMMANDS"; + load_c <= '1'; + load_z <= '1'; + c6 <= '1'; + inc_ic <= '1'; + nextstate <= sync; + + -- SET/CLEAR FLAGS STATE -- + when flag => + report "SET/RESET FLAGS"; + load_z <= ir(23); + load_c <= ir(22); + cc4 <= '1' & ir(21); + cc5 <= '1' & ir(20); + inc_ic <= '1'; + nextstate <= sync; + + -- SYNC STATE -- + when sync => + if v_done = '1' then + nextstate <= if1; + else + nextstate <= sync; + end if; + + -- HALT STATE -- + when halt => + report "halted"; + halted <= '1'; + nextstate <= halt; + + end case; + end if; + end process; +end rtl; + Index: tags/arelease/cpu/units/demultiplexer1x4.vhd =================================================================== --- tags/arelease/cpu/units/demultiplexer1x4.vhd (nonexistent) +++ tags/arelease/cpu/units/demultiplexer1x4.vhd (revision 10) @@ -0,0 +1,35 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: demultiplexer1x4 +-- +-- PURPOSE: demultiplexer, one input, four outputs +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity demultiplexer1x4 is + port( selector: in std_logic_vector(1 downto 0); + data_in: in std_logic; + data_out_00: out std_logic; + data_out_01: out std_logic; + data_out_10: out std_logic; + data_out_11: out std_logic + ); + +end demultiplexer1x4; + +architecture rtl of demultiplexer1x4 is +begin + data_out_00 <= data_in when selector = "00" else '0'; + data_out_01 <= data_in when selector = "01" else '0'; + data_out_10 <= data_in when selector = "10" else '0'; + data_out_11 <= data_in when selector = "11" else '0'; +end rtl; + Index: tags/arelease/cpu/units/alu.vhd =================================================================== --- tags/arelease/cpu/units/alu.vhd (nonexistent) +++ tags/arelease/cpu/units/alu.vhd (revision 10) @@ -0,0 +1,131 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: alu +-- +-- PURPOSE: alu of scalar unit +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +use work.cfg.all; + +entity alu is + port( + a_in: in std_logic_vector(31 downto 0); + b_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + aluop: in std_logic_vector(3 downto 0); + op_select: in std_logic; + zero_out: out std_logic; + carry_out: out std_logic; + alu_out: out std_logic_vector(31 downto 0) + ); +end alu; + +architecture rtl of alu is + component multiplexer2 + generic ( + w : positive + ); + port ( + selector: in std_logic; + data_in_0: in std_logic_vector(w-1 downto 0); + data_in_1: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + for mux: multiplexer2 use entity work.multiplexer2(rtl); + + signal aluop_multiplexed: std_logic_vector(3 downto 0) := "0000"; + + signal left: unsigned(32 downto 0); + signal right: unsigned(32 downto 0); + signal mult_res: unsigned(31 downto 0); + signal carry: std_logic; + +begin + mux: multiplexer2 + generic map (w => 4) + port map (selector => op_select, data_in_0 => aluop, data_in_1 => "0000", + data_out => aluop_multiplexed); + + process (a_in, b_in, carry, left, right, aluop_multiplexed, mult_res) + variable alu_out_buffer: unsigned(32 downto 0); + begin + case aluop_multiplexed is + when "0000" | "0001" | "0100" => -- add / adc / inc - use same adder + alu_out_buffer := left + right + carry; + + when "0010" | "0011" | "0110" => -- sub / sbc / dec - use same subtractor + alu_out_buffer := left - right - carry; + + when "1000" => -- and (a and b) + alu_out_buffer := "0" & unsigned( a_in and b_in); + + when "1001" => -- or (a or b) + alu_out_buffer := "0" & unsigned(a_in or b_in); + + when "1010" => -- xor (a xor b) + alu_out_buffer := "0" & unsigned(a_in xor b_in); + + when "1011" => -- mult (a(15:0) * b(15:0) + alu_out_buffer := "0" & mult_res; + + when "1100" => -- lsl (a shift left, insert 0) + alu_out_buffer(32 downto 1) := left(31 downto 0); + alu_out_buffer(0) := '0'; + + when "1110" => -- lsr (a shift right, insert 0) + alu_out_buffer(32) := left(0); + alu_out_buffer(30 downto 0) := left(31 downto 1); + alu_out_buffer(31) := '0'; + + when "1101" => -- rol (a shift left, insert c) + alu_out_buffer(32 downto 1) := left(31 downto 0); + alu_out_buffer(0) := carry; + + when "1111" => -- ror (a shift right, insert c) + alu_out_buffer(32) := left(0); + alu_out_buffer(30 downto 0) := left(31 downto 1); + alu_out_buffer(31) := carry; + + when others => -- not defined + alu_out_buffer := (others => '0'); + end case; + + alu_out <= std_logic_vector(alu_out_buffer(31 downto 0)); + carry_out <= alu_out_buffer(32); + + if(alu_out_buffer(31 downto 0) = 0) then + zero_out <= '1'; + else + zero_out <= '0'; + end if; + end process; + + left <= unsigned ("0" & a_in); + + right <= (others => '0') when (aluop_multiplexed = "0100" or aluop_multiplexed = "0110") + else unsigned ("0" & b_in); + + carry <= '0' when (aluop_multiplexed = "0000" or aluop_multiplexed = "0010") + else '1' when (aluop_multiplexed = "0100" or aluop_multiplexed = "0110") + else carry_in; + + mult_gen: if use_scalar_mult generate + mult_res <= left(15 downto 0) * right(15 downto 0); + end generate; + + not_mult_gen: if not use_scalar_mult generate + mult_res <= (others => '0'); + end generate; +end rtl; + Index: tags/arelease/cpu/units/instructioncounter.vhd =================================================================== --- tags/arelease/cpu/units/instructioncounter.vhd (nonexistent) +++ tags/arelease/cpu/units/instructioncounter.vhd (revision 10) @@ -0,0 +1,54 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: instructioncounter +-- +-- PURPOSE: instruction counter +-- basically a 32 bit register with increment +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity instructioncounter is + port( clk: in std_logic; + load: in std_logic; + inc: in std_logic; + reset: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); +end instructioncounter; + +architecture rtl of instructioncounter is + signal data_out_buffer: unsigned(31 downto 0); +begin + process + begin + wait until clk='1' and clk'event; + if reset = '1' then + data_out_buffer <= "00000000000000000000000000000000"; + else + if load = '1' and inc = '0' then + data_out_buffer <= unsigned(data_in); + end if; + + if load = '0' and inc = '1' then + data_out_buffer <= data_out_buffer + inc; + end if; + + if (load = inc) then + data_out_buffer <= data_out_buffer; + end if; + end if; + end process; + + data_out <= std_logic_vector(data_out_buffer); + +end rtl; + Index: tags/arelease/cpu/units/debugger.vhd =================================================================== --- tags/arelease/cpu/units/debugger.vhd (nonexistent) +++ tags/arelease/cpu/units/debugger.vhd (revision 10) @@ -0,0 +1,808 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: debugger +-- +-- PURPOSE: debugger for clvp +-- controls cpu via rs232 +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity debugger is + port ( + clk_in: in std_logic; -- use 50mhz for rs232 timing + + clk_cpu: out std_logic; + clk_mem: out std_logic; + + reset_out: out std_logic; + + rs232_txd: out std_logic; + rs232_rxd: in std_logic; + + a: in std_logic_vector(31 downto 0); + x: in std_logic_vector(31 downto 0); + y: in std_logic_vector(31 downto 0); + + ir: in std_logic_vector(31 downto 0); + ic: in std_logic_vector(31 downto 0); + + mem_switch: out std_logic; + mem_ready: in std_logic; + + mem_access: in std_logic_vector(2 downto 0); + mem_access_dbg: out std_logic_vector(2 downto 0); + + mem_addr: in std_logic_vector(31 downto 0); + mem_addr_dbg: out std_logic_vector(31 downto 0); + + mem_data: in std_logic_vector(31 downto 0); + mem_data_dbg: out std_logic_vector(31 downto 0); + + carry: in std_logic; + zero: in std_logic; + ir_ready: in std_logic; + halted: in std_logic + ); +end debugger; + +architecture rtl of debugger is + component rs232 -- code from michael schäferling + generic( DATABITS: integer:= 8; + STARTBITS: integer:= 1; + STOPBITS: integer:= 1 + ); + port( CLK_50MHZ : in std_logic; + RS232_RXD : in std_logic; + RS232_TXD : out std_logic; + + DATA_TX : in std_logic_vector(DATABITS-1 downto 0); + TX_SEND_DATA : in std_logic; + TX_BUSY : out std_logic; + + DATA_RX : out std_logic_vector(DATABITS-1 downto 0); + RX_DATA_RCVD : out std_logic; + RX_BUSY : out std_logic + ); + end component; + + component bufg + port ( + i: in std_logic; + o: out std_logic + ); + end component; + + + for rs232_impl: rs232 use entity work.rs232(Behavioral); + + signal data_tx: std_logic_vector(7 downto 0); + signal data_rx: std_logic_vector(7 downto 0); + signal tx_busy: std_logic; + signal rx_busy: std_logic; + signal data_received: std_logic; + signal send_data: std_logic; + + signal clk_buffer_cpu, clk_buffer_mem: std_logic; + + -- statemachine debugger + type statetype is (waiting, decode, clock, reset1, reset2, flags, rega, regx, + regy, regir, regic, busy8, init8, sending8, busy32, init32, sending32, inc32, echo, + ma, md, go, pause, to_fetch_address, to_fetch_data, fetch_address, fetch_data, to_normal, + mem_read1, mem_read2, mem_read3,mem_read4, mem_write1, mem_write2, mem_write3, mem_write4, + mem_restore1, mem_restore2, mem_restore3, mem_restore4, send_checksum, startcc, stopcc, + ccstatus, getcc); + + signal state : statetype := waiting; + signal nextstate : statetype := waiting; + + -- statemachine clock logic + type clocktype is (high, low, freehigh, freelow, memorylow, memoryhigh, ccountstart, ccountlow, ccounthigh); + signal clockstate : clocktype := low; + signal nextclockstate : clocktype := low; + + signal counter : std_logic_vector(1 downto 0) := "00"; + signal inc: std_logic; + + signal clockcounter : std_logic_vector(31 downto 0) := (others => '0'); + signal clockcounter_inc, clockcounter_res : std_logic; + + signal in_buffer: std_logic_vector(31 downto 0); + signal out_buffer: std_logic_vector(31 downto 0) := (others => '0'); + + signal ar: std_logic_vector(31 downto 0) := (others => '0'); + signal ar_shift: std_logic; + + signal dr: std_logic_vector(31 downto 0) := (others => '0'); + signal dr_shift: std_logic; + + signal load, load_mem_data: std_logic; + signal tofree, todebug, tomemory, clocktick : std_logic; + signal startclockcount, stopclockcount, clockcountstatus : std_logic; + + signal status: std_logic_vector(1 downto 0) := (others => '0'); + signal st_input: std_logic_vector(1 downto 0); + signal st_set: std_logic; + + signal checksum : std_logic_vector(7 downto 0); + +begin + rs232_impl: rs232 + generic map (DATABITS => 8, STARTBITS => 1, STOPBITS => 1) + port map ( + CLK_50MHZ => clk_in, RS232_RXD => rs232_rxd, RS232_TXD => rs232_txd, + DATA_TX => data_tx, TX_SEND_DATA => send_data, TX_BUSY => tx_busy, + DATA_RX => data_rx, RX_DATA_RCVD => data_received, RX_BUSY => rx_busy + ); + + gbuf_for_clk_cpu: bufg + port map ( + i => clk_buffer_cpu, + o => clk_cpu + ); + + gbuf_for_clk_mem: bufg + port map ( + i => clk_buffer_mem, + o => clk_mem + ); + + + -- counter + process + begin + wait until clk_in='1' and clk_in'event; + counter <= counter; + clockcounter <= clockcounter; + + if inc = '1' then + counter <= counter + '1'; + end if; + + if clockcounter_inc = '1' then + clockcounter <= clockcounter +1; + else + if clockcounter_res = '1' then + clockcounter <= (others => '0'); + end if; + end if; + + end process; + + -- register + process + begin + wait until clk_in='1' and clk_in'event; + + out_buffer <= out_buffer; + status <= status; + + ar <= ar; + dr <= dr; + + + if load = '1' then + out_buffer <= in_buffer; + else + if load_mem_data = '1' then + out_buffer <= mem_data; + end if; + end if; + + if ar_shift = '1' then + ar(31 downto 8) <= ar(23 downto 0); + ar(7 downto 0) <= data_rx; + end if; + + if dr_shift = '1' then + dr(31 downto 8) <= dr(23 downto 0); + dr(7 downto 0) <= data_rx; + end if; + + if st_set = '1' then + status <= st_input; + end if; + + end process; + + mem_addr_dbg <= ar; + mem_data_dbg <= dr; + checksum <= out_buffer(31 downto 24) xor out_buffer(23 downto 16) + xor out_buffer(15 downto 8) xor out_buffer(7 downto 0); + + -- state register + process + begin + wait until clk_in='1' and clk_in'event; + state <= nextstate; + clockstate <= nextclockstate; + + end process; + + -- clock state machine + process (clockstate, tofree, todebug, tomemory, clocktick, clockcounter_inc, clockcounter_res, clockcounter, ic, + startclockcount, stopclockcount, ar) + begin + -- avoid latches + clk_buffer_cpu <= '0'; + clk_buffer_mem <= '0'; + clockcountstatus <= '1'; + clockcounter_inc <= '0'; + clockcounter_res <= '0'; + + case clockstate is + -- CLOCK COUNTING STATES -- + when ccountstart => -- start clock counting + clockcounter_inc <= '0'; + clockcounter_res <= '1'; + clockcountstatus <= '0'; + nextclockstate <= ccountlow; + + when ccountlow => -- generate clock low signal + clockcountstatus <= '0'; + clk_buffer_cpu <= '0'; + clk_buffer_mem <= '0'; + + if stopclockcount = '1' then + nextclockstate <= low; + else + if ic = ar then -- stop when instruction counter value matches given address + nextclockstate <= low; + else + nextclockstate <= ccounthigh; + end if; + end if; + + + when ccounthigh => -- generate clock high signal + clockcountstatus <= '0'; + clockcounter_inc <= '1'; + clk_buffer_cpu <= '1'; + clk_buffer_mem <= '1'; + + if stopclockcount = '1' then + nextclockstate <= low; + else + nextclockstate <= ccountlow; + end if; + + -- DEBUG MODE STATES -- + when low => -- generate clock low signal + clk_buffer_cpu <= '0'; + clk_buffer_mem <= '0'; + + if startclockcount = '1' then -- only allow to start clockcount from debug mode + nextclockstate <= ccountstart; + else + if tomemory = '1' then + nextclockstate <= memorylow; + else + if tofree = '1' then + nextclockstate <= freelow; + else + if clocktick = '1' then + nextclockstate <= high; + else + nextclockstate <= low; + end if; + end if; + end if; + end if; + + when high => -- generate clock high signal + clk_buffer_cpu <= '1'; + clk_buffer_mem <= '1'; + + if tomemory = '1' then + nextclockstate <= memorylow; + else + if tofree = '1' then + nextclockstate <= freelow; + else + nextclockstate <= low; + end if; + end if; + + + -- FREE RUNNING MODE STATES -- + when freelow => -- generate clock low signal + clk_buffer_cpu <= '0'; + clk_buffer_mem <= '0'; + + if tomemory = '1' then + nextclockstate <= memorylow; + else + if todebug = '1' then + nextclockstate <= low; + else + nextclockstate <= freehigh; + end if; + end if; + + + when freehigh => -- generate clock high signal + clk_buffer_cpu <= '1'; + clk_buffer_mem <= '1'; + + if tomemory = '1' then + nextclockstate <= memorylow; + else + if todebug = '1' then + nextclockstate <= low; + else + nextclockstate <= freelow; + end if; + end if; + + + -- CLOCK MEMORY ONLY STATES -- + when memorylow => -- generate memory clock low signal + clk_buffer_mem <= '0'; + + if todebug = '1' then + nextclockstate <= low; + else + nextclockstate <= memoryhigh; + end if; + + when memoryhigh => -- generate memory clock high signal + clk_buffer_mem <= '1'; + + if todebug = '1' then + nextclockstate <= low; + else + nextclockstate <= memorylow; + end if; + + end case; + end process; + + -- debugger state machine + process (clk_in, data_rx, a, x, y, ir, ic, carry, zero, ir_ready, tx_busy, data_received, counter, + state, out_buffer, mem_addr, mem_data, mem_access, mem_ready, halted, status, checksum, + clockcountstatus, clockcounter ) + begin + -- avoid latches + reset_out <= '0'; + send_data <= '0'; + data_tx <= (others => '0'); + in_buffer <= (others => '0'); + nextstate <= waiting; + inc <= '0'; + load <= '0'; + + tofree <= '0'; + todebug <= '0'; + tomemory <= '0'; + clocktick <= '0'; + + ar_shift <= '0'; + dr_shift <= '0'; + + st_input <= (others => '0'); + st_set <= '0'; + + mem_switch <= '0'; + mem_access_dbg <= "000"; + load_mem_data <= '0'; + + startclockcount <= '0'; + stopclockcount <= '0'; + + case state is + -- WAIT FOR COMMANDS / DATA -- + when waiting => + if data_received = '1' then + nextstate <= decode; + else + nextstate <= waiting; + end if; + + -- DECODE STATE -- + when decode => + case status is + when "00" => -- normal modus + case data_rx is + when "01100011" | "01000011" => -- c/C = clock + nextstate <= clock; + + when "01110010" | "01010010" => -- r/R = reset + nextstate <= reset1; + + when "01100110" | "01000110" => -- f/F = flags + nextstate <= flags; + + when "01100001" | "01000001" => -- a/A = register a + nextstate <= rega; + + when "01111000" | "01011000" => -- x/X = register x + nextstate <= regx; + + when "01111001" | "01011001" => -- y/Y = register y + nextstate <= regy; + + when "01101001" | "01001001" => -- i/I = instruction register + nextstate <= regir; + + when "01101010" | "01001010" => -- j/J = instruction counter + nextstate <= regic; + + when "01101101" | "01001101" => -- m/M = memory data + nextstate <= md; + + when "01101110" | "01001110" => -- n/N = memory address + nextstate <= ma; + + when "01100111" | "01000111" => -- g/G = enter free-running-mode + nextstate <= go; + + when "01110000" | "01010000" => -- p/P = leave free-running-mode + nextstate <= pause; + + when "00110000" => -- 0 = fetch address + nextstate <= to_fetch_address; + + when "00110001" => -- 1 = fetch data + nextstate <= to_fetch_data; + + when "00110010" => -- 2 = read from memory + nextstate <= mem_read1; + + when "00110011" => -- 3 = write to memory + nextstate <= mem_write1; + + when "00110100" => -- 4 = enter clock count mode + nextstate <= startcc; + + when "00110101" => -- 5 = stop clock count mode + nextstate <= stopcc; + + when "00110110" => -- 6 = clock count status + nextstate <= ccstatus; + + when "00110111" => -- 7 = get clock counter + nextstate <= getcc; + + when others => -- unknown command, echo + nextstate <= echo; + end case; + + when "01" => -- receiving memory write command + nextstate <= fetch_address; + + when "10" => -- receiving memory read command + nextstate <= fetch_data; + + when others => + nextstate <= to_normal; + + end case; + + -- CLOCKCOUNTER STATS -- + when startcc => -- start clock counter + startclockcount <= '1'; + nextstate <= echo; + + when stopcc => -- stop clock counter + stopclockcount <= '1'; + nextstate <= echo; + + when ccstatus => -- get status of clock counter + in_buffer(7 downto 1) <= (others => '0'); + in_buffer(0) <= clockcountstatus; + load <= '1'; + nextstate <= busy8; + + when getcc => -- get clockcounter value + in_buffer(31 downto 0) <= clockcounter; + load <= '1'; + nextstate <= busy32; + + + -- READ MEMORY STATES -- + when mem_read1 => -- complete operation from cpu + tomemory <= '1'; + if mem_ready = '0' then + nextstate <= mem_read1; + else + nextstate <= mem_read2; + end if; + + when mem_read2 => -- switch from cpu to debugger control + mem_switch <= '1'; + nextstate <= mem_read3; + + when mem_read3 => -- start operation + mem_switch <= '1'; + mem_access_dbg <= "010"; + + if mem_ready = '1' then + nextstate <= mem_read3; + else + nextstate <= mem_read4; + end if; + + when mem_read4 => -- finish operation + mem_switch <= '1'; + mem_access_dbg <= "010"; + + load_mem_data <= '1'; + + if mem_ready = '1' then + nextstate <= mem_restore1; + else + nextstate <= mem_read4; + end if; + + + -- WRITE MEMORY STATES -- + when mem_write1 => -- complete operation from cpu + tomemory <= '1'; + + if mem_ready = '0' then + nextstate <= mem_write1; + else + nextstate <= mem_write2; + end if; + + when mem_write2 => -- switch from cpu to debugger control + mem_switch <= '1'; + nextstate <= mem_write3; + + + when mem_write3 => -- start operation + mem_switch <= '1'; + mem_access_dbg <= "100"; + + if mem_ready = '0' then + nextstate <= mem_write4; + else + nextstate <= mem_write3; + end if; + + when mem_write4 => -- finish operation + mem_switch <= '1'; + mem_access_dbg <= "100"; + + if mem_ready = '1' then + nextstate <= mem_restore1; + else + nextstate <= mem_write4; + end if; + + + -- RESTORE PREVIOUS MEMORY STATES -- + when mem_restore1 => -- switch from debugger to cpu control + mem_switch <= '1'; + nextstate <= mem_restore2; + + when mem_restore2 => + nextstate <= mem_restore3; + + when mem_restore3 => -- wait for completition + if mem_ready = '0' then + nextstate <= mem_restore3; + else + nextstate <= mem_restore4; + end if; + + when mem_restore4 => -- send back answer via rs232 + todebug <= '1'; + + if data_rx = "00110010" then + nextstate <= busy32; -- read (send 32 bit data back) + else + nextstate <= echo; -- write (send ok back) + end if; + + + -- FETCH ADDRESS VALUE -- + when fetch_address => + inc <= '1'; + ar_shift <= '1'; + + if counter = "11" then + nextstate <= to_normal; + else + nextstate <= echo; + end if; + + -- FETCH DATA VALUE -- + when fetch_data => + inc <= '1'; + dr_shift <= '1'; + + if counter = "11" then + nextstate <= to_normal; + else + nextstate <= echo; + end if; + + -- SWITCH TO FETCH ADDRESS MODE -- + when to_fetch_address => + st_input <= "01"; + st_set <= '1'; + nextstate <= echo; + + -- SWITCH TO FETCH DATA MODE -- + when to_fetch_data => + st_input <= "10"; + st_set <= '1'; + nextstate <= echo; + + -- SWITCH TO NORMAL ADDRESS MODE -- + when to_normal => + st_input <= "00"; + st_set <= '1'; + nextstate <= echo; + + -- SWITCH OT FREE RUNNING MODE -- + when go => + tofree <= '1'; + nextstate <= echo; + + -- END FREE RUNNING MODE -- + when pause => + todebug <= '1'; + nextstate <= echo; + + -- GENERATE ONE CLOCKTICK -- + when clock => + clocktick <= '1'; + nextstate <= echo; + + -- RESET CPU -- + when reset1 => + reset_out <= '1'; + clocktick <= '1'; + nextstate <= reset2; + + when reset2 => + reset_out <= '1'; + nextstate <= echo; + + -- SEND FLAGS -- + when flags => + in_buffer(7 downto 0) <= ir_ready & mem_ready & mem_access & halted & zero & carry; + load <= '1'; + nextstate <= busy8; + + -- SEND AKKUMULATOR -- + when rega => + in_buffer(31 downto 0) <= a; + load <= '1'; + nextstate <= busy32; + + -- SEND REGISTER X -- + when regx => + in_buffer(31 downto 0) <= x; + load <= '1'; + nextstate <= busy32; + + -- SEND REGISTER > -- + when regy => + in_buffer(31 downto 0) <= y; + load <= '1'; + nextstate <= busy32; + + -- SEND INSTRUCTION REGISTER -- + when regir => + in_buffer(31 downto 0) <= ir; + load <= '1'; + nextstate <= busy32; + + -- SEND INSTRUCTION COUNTER -- + when regic => + in_buffer(31 downto 0) <= ic; + load <= '1'; + nextstate <= busy32; + + -- SEND MEMORY ADDRESS -- + when ma => + in_buffer(31 downto 0) <= mem_addr; + load <= '1'; + nextstate <= busy32; + + -- SEND MEMORY DATA -- + when md => + in_buffer(31 downto 0) <= mem_data; + load <= '1'; + nextstate <= busy32; + + -- SEND RECEIVED COMMAND BACK -- + when echo => + in_buffer(7 downto 0) <= data_rx; + load <= '1'; + nextstate <= busy8; + + + -- COMMON SENDING ROUTINES -- + when busy8 => + if tx_busy = '0' then + nextstate <= init8; + else + nextstate <= busy8; + end if; + + when init8 => + data_tx <= out_buffer(7 downto 0); + send_data <= '1'; + + if tx_busy = '1' then + nextstate <= sending8; + else + nextstate <= init8; + end if; + + when sending8 => + if tx_busy = '0' then + nextstate <= waiting; + else + nextstate <= sending8; + end if; + + when busy32 => + if tx_busy = '0' then + nextstate <= init32; + else + nextstate <= busy32; + end if; + + when init32 => + case counter is + when "00" => + data_tx <= out_buffer(7 downto 0); + when "01" => + data_tx <= out_buffer(15 downto 8); + when "10" => + data_tx <= out_buffer(23 downto 16); + when "11" => + data_tx <= out_buffer(31 downto 24); + when others => + data_tx <= (others => '0'); + end case; + + send_data <= '1'; + + if tx_busy = '1' then + nextstate <= sending32; + else + nextstate <= init32; + end if; + + when sending32 => + if tx_busy = '0' then + nextstate <= inc32; + else + nextstate <= sending32; + end if; + + when inc32 => + inc <= '1'; + + if counter = "11" then + nextstate <= send_checksum; + else + nextstate <= busy32; + end if; + + -- send checksum for 32 bit data + when send_checksum => + data_tx <= checksum; + send_data <= '1'; + + if tx_busy = '1' then + nextstate <= sending8; + else + nextstate <= send_checksum; + end if; + + end case; + end process; +end rtl; \ No newline at end of file Index: tags/arelease/cpu/units/memoryinterface.vhd =================================================================== --- tags/arelease/cpu/units/memoryinterface.vhd (nonexistent) +++ tags/arelease/cpu/units/memoryinterface.vhd (revision 10) @@ -0,0 +1,220 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: memoryinterface +-- +-- PURPOSE: memory interface +-- for sram +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +-- WE, OE, SELECT +-- high-active, high-active, 0..scalar 1..vector + +entity memoryinterface is + port ( + clk: in std_logic; + address: in std_logic_vector(31 downto 0) := (others => '0'); + access_type: in std_logic_vector(2 downto 0) := "000"; -- we, oe, cs + data_in: in std_logic_vector(31 downto 0); + vdata_in: in vectordata_type; + data_out: out std_logic_vector(31 downto 0); + vdata_out: out vectordata_type; + ready: out std_logic; + we: out std_logic; + en: out std_logic; + addr: out std_logic_vector(31 downto 0); + di: out std_logic_vector(31 downto 0); + do: in std_logic_vector(31 downto 0) + ); +end memoryinterface; + +architecture rtl of memoryinterface is + + signal vload : std_logic; + signal vdata_buffer : vectordata_type := (others => (others => '0')); + + signal inc: std_logic; + signal res: std_logic; + signal index: integer range 0 to k-1; + signal counter : std_logic_vector(31 downto 0) := (others => '0'); + + type statetype is (waiting, rw, vr1, vr2, vw1, vw2, vdone1, vdone2); + signal state : statetype := waiting; + signal nextstate : statetype := waiting; + +begin + -- derive index from counter + index <= conv_integer(counter) when (counter < k) else 0; + + -- counter + process + begin + wait until clk='1' and clk'event; + counter <= counter; + + if res = '1' then + counter <= (others => '0'); + else + if inc = '1' then + counter <= counter + '1'; + end if; + end if; + end process; + + + -- vregister + process + begin + wait until clk='1' and clk'event; + if vload = '1' then + vdata_buffer(index) <= do; + else + vdata_buffer(index) <= vdata_buffer(index); + end if; + end process; + + -- state register + process + begin + wait until clk='1' and clk'event; + state <= nextstate; + end process; + + -- state transition + process (clk, address, access_type, data_in, vdata_in, state, do, index, counter) + begin + ready <= '0'; + nextstate <= waiting; + + res <= '0'; + inc <= '0'; + + vload <= '0'; + + we <= '0'; + en <= '0'; + addr <= (others => '0'); + di <= (others => '0'); + + case state is + -- WAITING STATE + when waiting => + ready <= '1'; + + case access_type is + when "010" => -- scalar read + ready <= '0'; + en <= '1'; + addr <= address; + + nextstate <= rw; + + when "100" => -- scalar write + ready <= '0'; + en <= '1'; + addr <= address; + we <= '1'; + di <= data_in; + + nextstate <= rw; + + when "011" => -- vector read + ready <= '0'; + nextstate <= vr1; + + when "101" => -- scalar write + ready <= '0'; + nextstate <= vw1; + + when others => + nextstate <= waiting; + end case; + + -- READ/WRITE DONE STATE + when rw => + en <= '1'; + addr <= address; + ready <= '1'; + + if access_type = "000" then + nextstate <= waiting; + else + nextstate <= rw; + end if; + + + -- VECTOR READ STATES + when vr1 => + en <= '1'; + addr <= address + counter; + nextstate <= vr2; + + when vr2 => + en <= '1'; + addr <= address + counter; + + inc <= '1'; + vload <= '1'; + + if counter = k-1 then + nextstate <= vdone1; + else + nextstate <= vr1; + end if; + + -- VECTOR WRITE STATES + when vw1 => + en <= '1'; + we <= '1'; + addr <= address + counter; + di <= vdata_in(index); + + nextstate <= vw2; + + when vw2 => + en <= '1'; + addr <= address + counter; + vload <= '1'; + inc <= '1'; + + if counter = k-1 then + nextstate <= vdone1; + else + nextstate <= vw1; + end if; + + + -- VECTOR DONE STATE + when vdone1 => + res <= '1'; + nextstate <= vdone2; + + when vdone2 => + ready <= '1'; + + if access_type = "000" then + nextstate <= waiting; + else + nextstate <= vdone2; + end if; + end case; + end process; + + -- connect outputs + data_out <= do; + vdata_out <= vdata_buffer; +end; + Index: tags/arelease/cpu/units/shuffle.vhd =================================================================== --- tags/arelease/cpu/units/shuffle.vhd (nonexistent) +++ tags/arelease/cpu/units/shuffle.vhd (revision 10) @@ -0,0 +1,243 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: shuffle +-- +-- PURPOSE: shuffle vector registers +-- also required for vmov commands +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity shuffle is + port ( + clk: in std_logic; + shuffle_go: in std_logic; + shuffle_valid: out std_logic; + data_in_v: in vectordata_type; + data_in_w: in vectordata_type; + vn: in std_logic_vector(7 downto 0); + ssss: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + shuffle_out_sel: in std_logic_vector(1 downto 0); + data_out: out vectordata_type + ); +end shuffle; + +architecture rtl of shuffle is + constant unit_width: integer := max_shuffle_width / 4; + + signal v, w, shuffle_output, output : std_logic_vector(32 * k -1 downto 0); + signal input, reg: std_logic_vector (max_shuffle_width -1 downto 0); + signal perm00, perm01, perm10, permutation : std_logic_vector (max_shuffle_width -1 downto 0); + signal perm00_rev, perm01_rev, perm10_rev, permutation_rev : std_logic_vector (max_shuffle_width -1 downto 0); + + + signal reg_input: std_logic_vector(unit_width -1 downto 0); + + signal shift: std_logic; + signal source: std_logic; + signal sel: std_logic_vector(1 downto 0); + + type statetype is (waiting, shuffle); + signal state : statetype := waiting; + signal nextstate : statetype := waiting; + + signal counter: std_logic_vector(1 downto 0) := "00"; + signal inc, reset: std_logic; + +begin + -- convert input from array to std_logic_vector format + v_gen : for i in 0 to k-1 generate + v((i+1) * 32 -1 downto i * 32) <= data_in_v(i); + end generate v_gen; + + -- perform shuffle command + shuffle_gen: if use_shuffle generate + w_gen : for i in 0 to k-1 generate + w((i+1) * 32 -1 downto i * 32) <= data_in_w(i); + end generate w_gen; + + -- state register + process + begin + wait until clk ='1' and clk'event; + state <= nextstate; + end process; + + -- state transitions + process (state, counter, shuffle_go) + begin + -- avoid latches + inc <= '0'; + reset <= '0'; + shift <= '0'; + shuffle_valid <= '0'; + + case state is + -- WAITING STATE + when waiting => + shuffle_valid <= '1'; + reset <= '1'; + + if shuffle_go = '1' then + nextstate <= shuffle; + else + nextstate <= waiting; + end if; + + -- SHUFFLE STATE + when shuffle => + shift <= '1'; + inc <= '1'; + + if counter = "11" then + nextstate <= waiting; + else + nextstate <= shuffle; + end if; + end case; + end process; + + -- counter + process + begin + wait until clk ='1' and clk'event; + if reset = '1' then + counter <= (others => '0'); + else + if inc = '1' then + counter <= counter + '1'; + else + counter <= counter; + end if; + end if; + end process; + + -- shift register + process + begin + wait until clk ='1' and clk'event; + if shift = '1' then + reg(max_shuffle_width - unit_width -1 downto 0) <= reg(max_shuffle_width -1 downto unit_width); + reg(max_shuffle_width -1 downto max_shuffle_width - unit_width ) <= reg_input; + else + reg <= reg; + end if; + end process; + + -- multiplexer + reg_input <= permutation(1* unit_width -1 downto 0 * unit_width) when (sel = "00") else + permutation(2* unit_width -1 downto 1 * unit_width) when (sel = "01") else + permutation(3* unit_width -1 downto 2 * unit_width) when (sel = "10") else + permutation(4* unit_width- 1 downto 3 * unit_width); + + -- sel + sel <= vn(7 downto 6) when (counter = "11") else + vn(5 downto 4) when (counter = "10") else + vn(3 downto 2) when (counter = "01") else + vn(1 downto 0); + + --source + source <= ssss(3) when (counter = "11") else + ssss(2) when (counter = "10") else + ssss(1) when (counter = "01") else + ssss(0); + + -- input multiplexer + input <= v(max_shuffle_width -1 downto 0) when source = '0' else + w(max_shuffle_width -1 downto 0); + + + -- permutations + permutation_gen : for i in 0 to 3 generate + + perm_gen_10: for j in 0 to 1 generate + perm10((i*2+j+1) * unit_width/2 -1 downto (i*2+j)*unit_width/2) + <= input((j*4+i+1)* unit_width/2 -1 downto (j*4+i)* unit_width/2); + + perm10_rev((j*4+i+1)* unit_width/2 -1 downto (j*4+i)* unit_width/2) + <= reg((i*2+j+1) * unit_width/2 -1 downto (i*2+j)*unit_width/2); + end generate; + + perm_gen_01: for j in 0 to 3 generate + perm01((i*4+j+1) * unit_width/4 -1 downto (i*4+j)*unit_width/4) + <= input((j*4+i+1)* unit_width/4 -1 downto (j*4+i)* unit_width/4); + + perm01_rev((j*4+i+1)* unit_width/4 -1 downto (j*4+i)* unit_width/4) + <= reg((i*4+j+1) * unit_width/4 -1 downto (i*4+j)*unit_width/4); + end generate; + + perm_gen_00: for j in 0 to 7 generate + perm00((i*8+j+1) * unit_width/8 -1 downto (i*8+j)*unit_width/8) + <= input((j*4+i+1)* unit_width/8 -1 downto (j*4+i)* unit_width/8); + + perm00_rev((j*4+i+1)* unit_width/8 -1 downto (j*4+i)* unit_width/8) + <= reg((i*8+j+1) * unit_width/8 -1 downto (i*8+j)*unit_width/8); + end generate; + + end generate; + + + -- vwidth multiplexer + permutation <= input when (vwidth = "11") else + perm10 when (vwidth = "10") else + perm01 when (vwidth = "01") else + perm00; + + permutation_rev <= reg when (vwidth = "11") else + perm10_rev when (vwidth = "10") else + perm01_rev when (vwidth = "01") else + perm00_rev; + + + -- output multiplexer + shuffle_output(max_shuffle_width -1 downto 0) <= permutation_rev(max_shuffle_width -1 downto 0); + + greater_gen: if (k*32 > max_shuffle_width) generate + shuffle_output(k*32-1 downto max_shuffle_width) <= v(k*32-1 downto max_shuffle_width); + end generate greater_gen; + end generate; + + -- move + not_shuffle_not_shift_gen: if ((not use_shuffle) and (not use_vectorshift)) generate + output <= v; + end generate; + + -- move and shuffle + shuffle_not_shift_gen: if ((use_shuffle) and (not use_vectorshift)) generate + output <= shuffle_output when shuffle_out_sel(0) = '0' else v; + end generate; + + -- move and vectorshift + not_shuffle_shift_gen: if ((not use_shuffle) and (use_vectorshift)) generate + output <= v(vectorshift_width -1 downto 0) & v(32*k-1 downto vectorshift_width) when shuffle_out_sel = "10" else + v(32*k-vectorshift_width-1 downto 0) & v(32*k-1 downto 32*k-vectorshift_width) when shuffle_out_sel = "11" else + v; + end generate; + + -- move, shuffle and vectorshift + shuffle_shift_gen: if ((use_shuffle) and (use_vectorshift)) generate + output <= shuffle_output when shuffle_out_sel = "00" else + v when shuffle_out_sel = "01" else + v(vectorshift_width -1 downto 0) & v(32*k-1 downto vectorshift_width) when shuffle_out_sel = "10" else + v(32*k-vectorshift_width-1 downto 0) & v(32*k-1 downto 32*k-vectorshift_width); + end generate; + + -- convert output from std_logic_vector in array format + out_gen : for i in 0 to k-1 generate + data_out(i) <= output((i+1)* 32 -1 downto i * 32); + end generate out_gen; + +end rtl; Index: tags/arelease/cpu/units/multiplexer2.vhd =================================================================== --- tags/arelease/cpu/units/multiplexer2.vhd (nonexistent) +++ tags/arelease/cpu/units/multiplexer2.vhd (revision 10) @@ -0,0 +1,35 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: multiplexer2 +-- +-- PURPOSE: multiplexer, two inputs +-- one output +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity multiplexer2 is + generic ( + w : positive -- word width + ); + port ( + selector: in std_logic; + data_in_0: in std_logic_vector(w-1 downto 0); + data_in_1: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); +end multiplexer2; + +architecture rtl of multiplexer2 is +begin + data_out <= data_in_0 when selector = '0' else + data_in_1; +end rtl; + Index: tags/arelease/cpu/units/multiplexer4.vhd =================================================================== --- tags/arelease/cpu/units/multiplexer4.vhd (nonexistent) +++ tags/arelease/cpu/units/multiplexer4.vhd (revision 10) @@ -0,0 +1,39 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: multiplexer4 +-- +-- PURPOSE: multiplexer, four inputs +-- one output +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity multiplexer4 is + generic ( + w : positive + ); + port ( + selector: in std_logic_vector(1 downto 0); + data_in_00: in std_logic_vector(w-1 downto 0); + data_in_01: in std_logic_vector(w-1 downto 0); + data_in_10: in std_logic_vector(w-1 downto 0); + data_in_11: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); +end multiplexer4; + +architecture rtl of multiplexer4 is +begin + data_out <= data_in_00 when selector = "00" else + data_in_01 when selector = "01" else + data_in_10 when selector = "10" else + data_in_11; +end rtl; + Index: tags/arelease/cpu/units/rs232.vhd =================================================================== --- tags/arelease/cpu/units/rs232.vhd (nonexistent) +++ tags/arelease/cpu/units/rs232.vhd (revision 10) @@ -0,0 +1,259 @@ +---------------------------------------------------------------------------------- +-- Company: Fachhochschule Augsburg - Fakultät für Informatik +-- Engineer: Schäferling Michael +-- +-- Create Date: 23:34:55 02/27/2007 +-- Design Name: +-- Module Name: rs232 - Behavioral +-- Project Name: +-- Target Devices: Xilinx +-- Tool versions: +-- Description: This module provides RS232 communication +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +---- Uncomment the following library declaration if instantiating +---- any Xilinx primitives in this code. +--library UNISIM; +--use UNISIM.VComponents.all; + +entity rs232 is + generic(DATABITS: integer:= 8; + STARTBITS: integer:= 1; + STOPBITS: integer:= 1 + ); + + port( -- HW signalling + CLK_50MHZ : in std_logic; + RS232_RXD: in std_logic; + RS232_TXD: out std_logic := '1'; + + -- internal DataCom + DATA_TX : in std_logic_vector(DATABITS-1 downto 0); + TX_SEND_DATA : in std_logic; + TX_BUSY : out std_logic := '0'; + + DATA_RX : out std_logic_vector(DATABITS-1 downto 0) := (others => '0'); + RX_DATA_RCVD : out std_logic := '0'; + RX_BUSY : out std_logic := '0' + ); +end rs232; + + + +architecture Behavioral of rs232 is + +type SER_STATES is (IDLE, SYN, B0, B1, B2, B3, B4, B5, B6, B7, VALID); + +signal SER_STATE: SER_STATES := IDLE; + + +signal CLK_38400: std_logic := '0'; +signal SIG_RST_TSER2: std_logic := '0'; +signal SIG_TSER2: std_logic := '0'; + +signal SIG_RST_TSER: std_logic := '0'; +signal SIG_TSER: std_logic := '0'; + + +begin + + + +-- Generate Signal for Serial Clock at 38400 +P_GEN_CLK38400: process (CLK_50MHZ) +-- 1302 == 10100010110 +constant CLK38400_MAX: std_logic_vector(10 downto 0) := "10100010110"; +variable CLK38400_CUR: std_logic_vector(10 downto 0) := "00000000000"; +begin + if CLK_50MHZ'event AND CLK_50MHZ='1' then + if CLK38400_CUR = CLK38400_MAX then + CLK38400_CUR := (others => '0'); + CLK_38400 <= '1'; + else + CLK38400_CUR := CLK38400_CUR + "00000000001"; + CLK_38400 <= '0'; + end if; + end if; +end process P_GEN_CLK38400; + + + +-- Generate Reset-driven Signal after Tser/2 +P_GEN_SIG_TSER2: process (CLK_50MHZ) +-- 651 == 1010001011 +constant TSER2_MAX: std_logic_vector(9 downto 0) := "1010001011"; +variable TSER2_CUR: std_logic_vector(9 downto 0) := "0000000000"; +begin + if CLK_50MHZ'event AND CLK_50MHZ='1' then + if SIG_RST_TSER2 = '1' then + SIG_TSER2 <= '0'; + TSER2_CUR := (others => '0'); + elsif TSER2_CUR = TSER2_MAX then + SIG_TSER2 <= '1'; + TSER2_CUR := (others => '0'); + else + SIG_TSER2 <= '0'; + TSER2_CUR := TSER2_CUR + "0000000001"; + end if; + end if; +end process P_GEN_SIG_TSER2; + + + +-- Generate Reset-driven Signal after Tser +P_GEN_SIG_TSER: process (CLK_50MHZ) +constant TSER_MAX: std_logic_vector(10 downto 0) := "10100010110"; +variable TSER_CUR: std_logic_vector(10 downto 0) := "00000000000"; +begin + if CLK_50MHZ'event AND CLK_50MHZ='1' then + if SIG_RST_TSER = '1' then + SIG_TSER <= '0'; + TSER_CUR := (others => '0'); + elsif TSER_CUR = TSER_MAX then + SIG_TSER <= '1'; + TSER_CUR := (others => '0'); + else + SIG_TSER <= '0'; + TSER_CUR := TSER_CUR + "00000000001"; + end if; + end if; +end process P_GEN_SIG_TSER; + + + +-- RX / TX Process +P_RX_TX: process (CLK_50MHZ) +constant TOKENSIZE: integer:= STARTBITS + DATABITS + STOPBITS; + +-- variables for RX +variable BYTE_RX: std_logic_vector(7 downto 0); + -- for testing +variable signcount: std_logic_vector(3 downto 0) := "0000"; + +-- variables for TX +variable SEND_TOKEN: std_logic := '0'; +variable TOKEN_OUT: std_logic_vector(TOKENSIZE-1 downto 0); +variable COUNT: std_logic_vector(3 downto 0) := "0000"; + +begin + if CLK_50MHZ'event AND CLK_50MHZ='1' then + -- RX + RX_BUSY <= '1'; + case SER_STATE is + when IDLE => if RS232_RXD = '0' then + SIG_RST_TSER2 <= '1'; + SER_STATE <= SYN; + RX_DATA_RCVD <= '0'; + else + RX_BUSY <= '0'; + SIG_RST_TSER2 <= '0'; + SER_STATE <= IDLE; + RX_DATA_RCVD <= '0'; + end if; + when SYN => if SIG_TSER2 = '1' then + SIG_RST_TSER2 <= '0'; + SIG_RST_TSER <= '1'; + SER_STATE <= B0; + else + SIG_RST_TSER2 <= '0'; + SIG_RST_TSER <= '0'; + SER_STATE <= SYN; + end if; + when B0 => if SIG_TSER = '1' then + SIG_RST_TSER <= '0'; + SER_STATE <= B1; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else + SIG_RST_TSER <= '0'; + SER_STATE <= B0; + end if; + when B1 => if SIG_TSER = '1' then + SER_STATE <= B2; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B1; + end if; + when B2 => if SIG_TSER = '1' then + SER_STATE <= B3; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B2; + end if; + when B3 => if SIG_TSER = '1' then + SER_STATE <= B4; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B3; + end if; + when B4 => if SIG_TSER = '1' then + SER_STATE <= B5; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B4; + end if; + when B5 => if SIG_TSER = '1' then + SER_STATE <= B6; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B5; + end if; + when B6 => if SIG_TSER = '1' then + SER_STATE <= B7; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B6; + end if; + when B7 => if SIG_TSER = '1' then + SER_STATE <= VALID; + BYTE_RX := RS232_RXD & BYTE_RX(7 downto 1); + else SER_STATE <= B7; + end if; + when VALID => if SIG_TSER = '1' then + if RS232_RXD = '1' then + DATA_RX <= BYTE_RX; + RX_DATA_RCVD <= '1'; + else + DATA_RX <= (others => '0'); + RX_DATA_RCVD <= '0'; + end if; + SER_STATE <= IDLE; + else + SER_STATE <= VALID; + end if; + end case; + + + -- TX + TX_BUSY <= '0'; + if TX_SEND_DATA = '1' AND SEND_TOKEN = '0' then + TOKEN_OUT := '1' & DATA_TX & '0'; + SEND_TOKEN := '1'; + end if; + + if SEND_TOKEN = '1' then + TX_BUSY <= '1'; + if CLK_38400 = '1' then + if COUNT < TOKENSIZE then + --TX_BUSY <= '1'; + COUNT := COUNT + "0001"; + -- send from right to left (LSB first) + RS232_TXD <= TOKEN_OUT(0); + TOKEN_OUT(TOKENSIZE-1 downto 0) := TOKEN_OUT(0) & TOKEN_OUT(TOKENSIZE-1 downto 1); + else + COUNT := "0000"; + SEND_TOKEN := '0'; + --TX_BUSY <= '0'; + end if; + end if; + --else + --TX_BUSY <= '0'; + end if; + end if; +end process P_RX_TX; + +end Behavioral; Index: tags/arelease/cpu/system.vhd =================================================================== --- tags/arelease/cpu/system.vhd (nonexistent) +++ tags/arelease/cpu/system.vhd (revision 10) @@ -0,0 +1,199 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: system +-- +-- PURPOSE: top level module of processor +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; +use work.datatypes.all; + +entity system is + port( + clk: in std_logic; + reset: in std_logic; + + rs232_txd: out std_logic; + rs232_rxd: in std_logic + ); +end system; + +architecture rtl of system is + + component cpu + port( + clk: in std_logic; + reset: in std_logic; + dbg_a: out std_logic_vector(31 downto 0); + dbg_x: out std_logic_vector(31 downto 0); + dbg_y: out std_logic_vector(31 downto 0); + dbg_ir: out std_logic_vector(31 downto 0); + dbg_ic: out std_logic_vector(31 downto 0); + dbg_carry: out std_logic; + dbg_zero: out std_logic; + dbg_ir_ready: out std_logic; + dbg_halted: out std_logic; + mem_data_in: in std_logic_vector(31 downto 0); + mem_data_out: out std_logic_vector(31 downto 0); + mem_vdata_in: in vectordata_type; + mem_vdata_out: out vectordata_type; + mem_address: out std_logic_vector(31 downto 0); + mem_access: out std_logic_vector(2 downto 0); + mem_ready: in std_logic + ); + end component; + + component memoryinterface + port ( + clk: in std_logic; + address: in std_logic_vector(31 downto 0) := (others => '0'); + access_type: in std_logic_vector(2 downto 0) := "000"; -- we, oe, cs + data_in: in std_logic_vector(31 downto 0); + vdata_in: in vectordata_type; + data_out: out std_logic_vector(31 downto 0); + vdata_out: out vectordata_type; + ready: out std_logic; + we: out std_logic; + en: out std_logic; + addr: out std_logic_vector(31 downto 0); + di: out std_logic_vector(31 downto 0); + do: in std_logic_vector(31 downto 0) + ); + end component; + + component debugger + port ( + clk_in: in std_logic; + clk_cpu: out std_logic; + clk_mem: out std_logic; + reset_out: out std_logic; + rs232_txd: out std_logic; + rs232_rxd: in std_logic; + a: in std_logic_vector(31 downto 0); + x: in std_logic_vector(31 downto 0); + y: in std_logic_vector(31 downto 0); + ir: in std_logic_vector(31 downto 0); + ic: in std_logic_vector(31 downto 0); + mem_switch: out std_logic; + mem_ready: in std_logic; + mem_access: in std_logic_vector(2 downto 0); + mem_access_dbg: out std_logic_vector(2 downto 0); + mem_addr: in std_logic_vector(31 downto 0); + mem_addr_dbg: out std_logic_vector(31 downto 0); + mem_data: in std_logic_vector(31 downto 0); + mem_data_dbg: out std_logic_vector(31 downto 0); + carry: in std_logic; + zero: in std_logic; + ir_ready: in std_logic; + halted: in std_logic + ); + end component; + + component sram + port ( + clk : in std_logic; + we : in std_logic; + en : in std_logic; + addr : in std_logic_vector(31 downto 0); + di : in std_logic_vector(31 downto 0); + do : out std_logic_vector(31 downto 0) + ); + end component; + + for sram_impl: sram use entity work.sram(rtl); + for cpu_impl: cpu use entity work.cpu(rtl); + for memoryinterface_impl: memoryinterface use entity work.memoryinterface(rtl); + for debugger_impl: debugger use entity work.debugger(rtl); + + + -- sram signals + signal we, en: std_logic; + signal addr, di, do: std_logic_vector(31 downto 0); + + -- debugger signals + signal clk_cpu: std_logic; + signal clk_mem: std_logic; + signal reset_cpu: std_logic; + signal mem_switch: std_logic; + + -- cpu signals + signal dbg_a, dbg_x, dbg_y, dbg_ir, dbg_ic: std_logic_vector(31 downto 0); + signal dbg_carry, dbg_zero, dbg_ir_ready, dbg_halted: std_logic; + + -- memory interface signals + signal mem_access, mem_access_cpu, mem_access_dbg: std_logic_vector(2 downto 0); + signal mem_address, mem_address_cpu, mem_address_dbg: std_logic_vector(31 downto 0); + signal mem_data_out, mem_data_out_cpu, mem_data_out_dbg: std_logic_vector(31 downto 0); + + signal mem_data_in: std_logic_vector(31 downto 0); + signal mem_vdata_in, mem_vdata_out: vectordata_type; + signal mem_ready: std_logic; + + -- attributes for xilinx synthesis tool + attribute clock_signal : string; + attribute clock_signal of "clk" : signal is "yes"; + attribute clock_signal of "clk_cpu" : signal is "yes"; + +begin + -- include debugger + debugger_gen: if use_debugger generate + debugger_impl: debugger + port map ( + clk_in => clk, clk_cpu => clk_cpu, clk_mem => clk_mem, reset_out => reset_cpu, + rs232_txd => rs232_txd, rs232_rxd => rs232_rxd, a => dbg_a, x => dbg_x, y => dbg_y, ir => + dbg_ir, ic => dbg_ic, mem_switch => mem_switch, mem_ready => mem_ready, mem_access => + mem_access_cpu, mem_access_dbg => mem_access_dbg, mem_addr => mem_address_cpu, + mem_addr_dbg => mem_address_dbg, mem_data => mem_data_in, mem_data_dbg => mem_data_out_dbg, + carry => dbg_carry, zero => dbg_zero, ir_ready => dbg_ir_ready, halted => dbg_halted + ); + + -- allow memory access from debugger unit + mem_access <= mem_access_cpu when mem_switch = '0' else mem_access_dbg; + mem_address <= mem_address_cpu when mem_switch = '0' else mem_address_dbg; + mem_data_out <= mem_data_out_cpu when mem_switch = '0' else mem_data_out_dbg; + end generate; + + -- dont include debugger + not_debugger_gen: if not use_debugger generate + reset_cpu <= reset; + clk_cpu <= clk; + + -- allow memory access only from cpu + mem_access <= mem_access_cpu; + mem_address <= mem_address_cpu; + mem_data_out <= mem_data_out_cpu; + end generate; + + cpu_impl: cpu + port map ( + clk => clk_cpu, reset => reset_cpu, dbg_a => dbg_a, dbg_x => dbg_x, dbg_y => dbg_y, + dbg_ir => dbg_ir, dbg_ic => dbg_ic, dbg_carry => dbg_carry, dbg_zero => dbg_zero, + dbg_ir_ready => dbg_ir_ready, dbg_halted => dbg_halted, mem_data_in => mem_data_in, + mem_data_out => mem_data_out_cpu, mem_vdata_in => mem_vdata_in, mem_vdata_out => mem_vdata_out, + mem_address => mem_address_cpu, mem_access => mem_access_cpu, mem_ready => mem_ready + ); + + + memoryinterface_impl: memoryinterface + port map ( + clk => clk_mem, address => mem_address, access_type => mem_access, data_in => mem_data_out, + vdata_in => mem_vdata_out, data_out => mem_data_in, vdata_out => mem_vdata_in, ready => mem_ready, + we => we, en => en, addr => addr, di => di, do => do + ); + + sram_impl: sram + port map ( + clk => clk_mem, we => we, en => en, addr => addr, di => di, do => do + ); + +end; + Index: tags/arelease/cpu/config.vhd =================================================================== --- tags/arelease/cpu/config.vhd (nonexistent) +++ tags/arelease/cpu/config.vhd (revision 10) @@ -0,0 +1,33 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: cfg +-- +-- PURPOSE: base configuration file +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package cfg is + -- configuration + constant n: integer := 10; -- amount of vector registers + constant k: integer := 20; -- amount words per vector register (even numbers) + + constant use_debugger: boolean := true; -- include debugging unit + + constant use_scalar_mult : boolean := true; -- allow multiplications in scalar alu + constant use_vector_mult : boolean := false; -- allow multiplications in vector alu + + constant use_shuffle : boolean := false; -- use shuffle unit + constant max_shuffle_width : integer := 0; -- max. shuffle width (dividable by 4) + + constant use_vectorshift : boolean := true; -- allow shift of vector registers (vmol, vmor) + constant vectorshift_width : integer := 32; -- width of vectorshift in bit + + constant sram_size : integer := 4096; -- sram size (memory size: 32 bit * sram_size) +end cfg; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_multiplexer2.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_multiplexer2.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_multiplexer2.vhd (revision 10) @@ -0,0 +1,73 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_multiplexer2 +-- +-- PURPOSE: testbench of multiplexer2 entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_multiplexer2 is +end tb_multiplexer2; + +architecture testbench of tb_multiplexer2 is + component multiplexer2 + generic ( + w : positive + ); + port( + selector: in std_logic; + data_in_0: in std_logic_vector(w-1 downto 0); + data_in_1: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + for impl: multiplexer2 use entity work.multiplexer2(rtl); + + signal selector: std_logic := '0'; + signal data_in_0: std_logic_vector(31 downto 0) := "00000000000000000000000000000000"; + signal data_in_1: std_logic_vector(31 downto 0) := "00000000000000000000000000000001"; + + signal data_out: std_logic_vector(31 downto 0); + + constant period : time := 2ns; + + begin + impl: multiplexer2 + generic map (w => 32) + port map (selector => selector, data_in_0 => data_in_0, data_in_1 => data_in_1, + data_out => data_out); + process + begin + wait for 100ns; + + -- selector = 0 + selector <= '0'; + + wait for period; + + assert data_out = "00000000000000000000000000000000" + report "selector=0 : data_out" + severity Error; + + -- selector = 1 + selector <= '1'; + + wait for period; + + assert data_out = "00000000000000000000000000000001" + report "selector=1 : data_out" + severity Error; + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_aluinputgroup.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_aluinputgroup.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_aluinputgroup.vhd (revision 10) @@ -0,0 +1,228 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_aluinputgrp +-- +-- PURPOSE: testbench of aluinputgroup entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_aluinputgroup is +end tb_aluinputgroup; + +architecture testbench of tb_aluinputgroup is + component aluinputgroup + port( + clk: in std_logic; + memory_in: in std_logic_vector(31 downto 0); + x_in: in std_logic_vector(31 downto 0); + y_in: in std_logic_vector(31 downto 0); + a_in: in std_logic_vector(31 downto 0); + ir_out: out std_logic_vector(31 downto 0); + k_out: out std_logic_vector(31 downto 0); + vector_out: out std_logic_vector(31 downto 0); + a_out: out std_logic_vector(31 downto 0); + b_out: out std_logic_vector(31 downto 0); + sel_a: in std_logic_vector(1 downto 0); + sel_b: in std_logic_vector(1 downto 0); + sel_source_a: in std_logic; + sel_source_b: in std_logic; + load_ir: in std_logic + ); + end component; + + for impl: aluinputgroup use entity work.aluinputgroup(rtl); + + signal clk: std_logic; + signal memory_in: std_logic_vector(31 downto 0); -- data from ram + signal x_in: std_logic_vector(31 downto 0); + signal y_in: std_logic_vector(31 downto 0); + signal a_in: std_logic_vector(31 downto 0); + signal ir_out: std_logic_vector(31 downto 0); + signal k_out: std_logic_vector(31 downto 0); -- k for vector unit + signal vector_out: std_logic_vector(31 downto 0); -- data for vector unit + signal a_out: std_logic_vector(31 downto 0); + signal b_out: std_logic_vector(31 downto 0); + signal sel_a: std_logic_vector(1 downto 0); + signal sel_b: std_logic_vector(1 downto 0); + signal sel_source_a: std_logic; -- c8 + signal sel_source_b: std_logic; -- c0 + signal load_ir: std_logic; + + constant period : time := 2ns; + + begin + impl: aluinputgroup port map (clk => clk, memory_in => memory_in, x_in => x_in, y_in => y_in, + a_in => a_in, ir_out => ir_out, k_out => k_out, vector_out => vector_out, a_out => a_out, + b_out => b_out, sel_a => sel_a, sel_b => sel_b, sel_source_a => sel_source_a, sel_source_b + => sel_source_b, load_ir => load_ir); + process + begin + wait for 100ns; + + -- 1: load ir, a_out register a, b_out memory, vector_out register a, k_out register x + memory_in <= "11010011110100111101001111010011"; + a_in <= "01001100010011000100110001001100"; + x_in <= "11001010110010101100101011001010"; + + load_ir <= '1'; + sel_source_a <= '0'; + sel_source_b <= '1'; + sel_a <= "01"; + sel_b <= "10"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ir_out = "11010011110100111101001111010011" + report "1 : ir_out" + severity Error; + + assert a_out = "01001100010011000100110001001100" + report "1 : a_out" + severity Error; + + assert b_out = "11010011110100111101001111010011" + report "1 : b_out" + severity Error; + + assert k_out = "11001010110010101100101011001010" + report "1 : k_out" + severity Error; + + assert vector_out = "01001100010011000100110001001100" + report "1 : vector_out" + severity Error; + + + -- 2: not load ir, a_out register y, b_out n, vector_out y, k_out n + y_in <= "10011001100110011001100110011001"; + + load_ir <= '0'; + sel_source_a <= '0'; + sel_source_b <= '0'; + sel_a <= "11"; + sel_b <= "00"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ir_out = "11010011110100111101001111010011" + report "2 : ir_out" + severity Error; + + assert a_out = "10011001100110011001100110011001" + report "2 : a_out" + severity Error; + + assert b_out = "00000000000000001101001111010011" + report "2 : b_out" + severity Error; + + assert k_out = "00000000000000001101001111010011" + report "2 : k_out" + severity Error; + + assert vector_out = "10011001100110011001100110011001" + report "2 : vector_out" + severity Error; + + + -- 3: not load ir, a_out 0, b_out a, vector_out 0, k_out register a + load_ir <= '0'; + sel_source_a <= '0'; + sel_source_b <= '0'; + sel_a <= "00"; + sel_b <= "01"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ir_out = "11010011110100111101001111010011" + report "3 : ir_out" + severity Error; + + assert a_out = "00000000000000000000000000000000" + report "3 : a_out" + severity Error; + + assert b_out = "01001100010011000100110001001100" + report "3 : b_out" + severity Error; + + assert k_out = "01001100010011000100110001001100" + report "3 : k_out" + severity Error; + + assert vector_out = "00000000000000000000000000000000" + report "3 : vector_out" + severity Error; + + -- 4: load ir, a_out register x, b_out select y, vector_out register x, k_out register y + memory_in <= "01101101011011010110110101101101"; + + load_ir <= '1'; + sel_source_a <= '0'; + sel_source_b <= '0'; + sel_a <= "10"; + sel_b <= "11"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ir_out = "01101101011011010110110101101101" + report "4 : ir_out" + severity Error; + + assert a_out = "11001010110010101100101011001010" + report "4 : a_out" + severity Error; + + assert b_out = "10011001100110011001100110011001" + report "4 : b_out" + severity Error; + + assert k_out = "10011001100110011001100110011001" + report "4 : k_out" + severity Error; + + assert vector_out = "11001010110010101100101011001010" + report "4 : vector_out" + severity Error; + + -- 5: load ir, a_out select 0, b_out register y, vector_out register x, k_out y + memory_in <= "01101101011011010110110101101101"; + + load_ir <= '1'; + sel_source_a <= '1'; + sel_source_b <= '0'; + sel_a <= "10"; + sel_b <= "11"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ir_out = "01101101011011010110110101101101" + report "5 : ir_out" + severity Error; + + assert a_out = "00000000000000000000000000000000" + report "5 : a_out" + severity Error; + + assert b_out = "10011001100110011001100110011001" + report "5 : b_out" + severity Error; + + assert k_out = "10011001100110011001100110011001" + report "5 : k_out" + severity Error; + + assert vector_out = "11001010110010101100101011001010" + report "5 : vector_out" + severity Error; + + wait; + end process; +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_dataregister.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_dataregister.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_dataregister.vhd (revision 10) @@ -0,0 +1,91 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_dataregister +-- +-- PURPOSE: testbench of dataregister entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_dataregister is +end tb_dataregister; + +architecture testbench of tb_dataregister is + component dataregister + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + for impl: dataregister use entity work.dataregister(rtl); + + signal clk: std_logic; + signal load: std_logic; + signal data_in: std_logic_vector(31 downto 0); + signal data_out: std_logic_vector(31 downto 0); + + constant period : time := 2ns; + + begin + impl: dataregister port map (clk => clk, load => load, data_in => data_in, + data_out => data_out); + process + begin + wait for 100ns; + + -- load 1 + data_in <= "11101110111011101110111011101110"; + load <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11101110111011101110111011101110" + report "load 1 : data_out" + severity Error; + + + -- load = 'Z' + data_in <= "00000000000000000000000000000001"; + load <= 'Z'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11101110111011101110111011101110" + report "load=z : data_out" + severity Error; + + + -- not load + data_in <= "11111111111111111111111111111111"; + load <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11101110111011101110111011101110" + report "not load: data_out" + severity Error; + + + -- load 2 + data_in <= "10101010101010101010101010101010"; + load <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "10101010101010101010101010101010" + report "load 2 : data_out" + severity Error; + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_multiplexer4.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_multiplexer4.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_multiplexer4.vhd (revision 10) @@ -0,0 +1,94 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_multiplexer4 +-- +-- PURPOSE: testbench of multiplexer4 entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_multiplexer4 is +end tb_multiplexer4; + +architecture testbench of tb_multiplexer4 is + component multiplexer4 + generic ( + w : positive + ); + port ( + selector: in std_logic_vector(1 downto 0); + data_in_00: in std_logic_vector(w-1 downto 0); + data_in_01: in std_logic_vector(w-1 downto 0); + data_in_10: in std_logic_vector(w-1 downto 0); + data_in_11: in std_logic_vector(w-1 downto 0); + data_out: out std_logic_vector(w-1 downto 0) + ); + end component; + + for impl: multiplexer4 use entity work.multiplexer4(rtl); + + signal selector: std_logic_vector(1 downto 0) := "00"; + signal data_in_00: std_logic_vector(31 downto 0) := "10101100101011001010110010101100"; + signal data_in_01: std_logic_vector(31 downto 0) := "11001001110010011100100111001001"; + signal data_in_10: std_logic_vector(31 downto 0) := "01100110011001100110011001100110"; + signal data_in_11: std_logic_vector(31 downto 0) := "11001111110011111100111111001111"; + signal data_out: std_logic_vector(31 downto 0); + + constant period : time := 2ns; + + begin + impl: multiplexer4 + generic map (w => 32) + port map (selector => selector, data_in_00 => data_in_00, data_in_01 => data_in_01, + data_in_10 => data_in_10, data_in_11 => data_in_11, data_out => data_out); + process + begin + wait for 100ns; + + -- selector = 00 + selector <= "00"; + + wait for period; + + assert data_out = "10101100101011001010110010101100" + report "selector=00 : data_out" + severity Error; + + -- selector = 01 + selector <= "01"; + + wait for period; + + assert data_out = "11001001110010011100100111001001" + report "selector=01 : data_out" + severity Error; + + -- selector = 10 + selector <= "10"; + + wait for period; + + assert data_out = "01100110011001100110011001100110" + report "selector=10 : data_out" + severity Error; + + -- selector = 11 + selector <= "11"; + + wait for period; + + assert data_out = "11001111110011111100111111001111" + report "selector=11 : data_out" + severity Error; + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_selectunit.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_selectunit.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_selectunit.vhd (revision 10) @@ -0,0 +1,144 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_selectunit +-- +-- PURPOSE: testbench of selectunit entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +use work.cfg.all; -- testbench requires k > 7 +use work.datatypes.all; + +entity tb_selectunit is +end tb_selectunit; + + + +architecture testbench of tb_selectunit is + component selectunit + port ( + data_in : in vectordata_type; + k_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + for impl: selectunit use entity work.selectunit(rtl); + + signal data_in: vectordata_type; + signal k_in: std_logic_vector(31 downto 0) := (others => '0'); + signal data_out: std_logic_vector(31 downto 0); + + constant period : time := 2ns; + + begin + impl: selectunit port map (data_in => data_in, k_in => k_in, data_out => data_out); + process + begin + wait for 100ns; + + assert k > 7 + report "testbench requires k > 7" + severity Error; + + data_in(0) <= "10101100110111001001111000101111"; + data_in(1) <= "01001011011011101010101101010100"; + data_in(2) <= "11101101110110101011011011101010"; + data_in(3) <= "11001100110011001100110011001101"; + data_in(4) <= "11001011001001100101110010011000"; + data_in(5) <= "10010010100100101001001010010010"; + data_in(6) <= "11111000000111111100000011111000"; + data_in(7) <= "10101010101010101010101010101010"; + + -- k = 0 + k_in <= "00000000000000000000000000000000"; + + wait for period; + + assert data_out = "10101100110111001001111000101111" + report "k=0 : data_out" + severity Error; + + + -- k = 1 + k_in <= "00000000000000000000000000000001"; + + wait for period; + + assert data_out = "01001011011011101010101101010100" + report "k=1 : data_out" + severity Error; + + + -- k = 2 + k_in <= "00000000000000000000000000000010"; + + wait for period; + + assert data_out = "11101101110110101011011011101010" + report "k=2 : data_out" + severity Error; + + -- k = 3 + k_in <= "00000000000000000000000000000011"; + + wait for period; + + assert data_out = "11001100110011001100110011001101" + report "k=3 : data_out" + severity Error; + + + -- k = 4 + k_in <= "00000000000000000000000000000100"; + + wait for period; + + assert data_out = "11001011001001100101110010011000" + report "k=4 : data_out" + severity Error; + + + -- k = 5 + k_in <= "00000000000000000000000000000101"; + + wait for period; + + assert data_out = "10010010100100101001001010010010" + report "k=5 : data_out" + severity Error; + + + -- k = 6 + k_in <= "00000000000000000000000000000110"; + + wait for period; + + assert data_out = "11111000000111111100000011111000" + report "k=6 : data_out" + severity Error; + + + + -- k = 7 + k_in <= "00000000000000000000000000000111"; + + wait for period; + + assert data_out = "10101010101010101010101010101010" + report "k=100000 : data_out" + severity Error; + + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_demultiplexer1x4.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_demultiplexer1x4.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_demultiplexer1x4.vhd (revision 10) @@ -0,0 +1,139 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_demultiplexer +-- +-- PURPOSE: testbench of demultiplexer entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_demultiplexer1x4 is +end tb_demultiplexer1x4; + +architecture testbench of tb_demultiplexer1x4 is + component demultiplexer1x4 + port( selector: in std_logic_vector(1 downto 0); + data_in: in std_logic; + data_out_00: out std_logic; + data_out_01: out std_logic; + data_out_10: out std_logic; + data_out_11: out std_logic + ); + end component; + + for impl: demultiplexer1x4 use entity work.demultiplexer1x4(rtl); + + signal selector: std_logic_vector(1 downto 0) := "00"; + signal data_in: std_logic := '1'; + signal data_out_00: std_logic; + signal data_out_01: std_logic; + signal data_out_10: std_logic; + signal data_out_11: std_logic; + + constant period : time := 2ns; + + begin + impl: demultiplexer1x4 port map (selector => selector, data_in => data_in, data_out_00 => data_out_00, + data_out_01 => data_out_01, data_out_10 => data_out_10, data_out_11 => data_out_11); + process + begin + wait for 100ns; + + -- selector = 00 + selector <= "00"; + + wait for period; + + assert data_out_00 = '1' + report "selector=00 : data_out_00" + severity Error; + + assert data_out_01 = '0' + report "selector=00 : data_out_01" + severity Error; + + assert data_out_10 = '0' + report "selector=00 : data_out_10" + severity Error; + + assert data_out_11 = '0' + report "selector=00 : data_out_11" + severity Error; + + + -- selector = 01 + selector <= "01"; + + wait for period; + + assert data_out_00 = '0' + report "selector=01 : data_out_00" + severity Error; + + assert data_out_01 = '1' + report "selector=01 : data_out_01" + severity Error; + + assert data_out_10 = '0' + report "selector=01 : data_out_10" + severity Error; + + assert data_out_11 = '0' + report "selector=01 : data_out_11" + severity Error; + + -- selector = 10 + selector <= "10"; + + wait for period; + + assert data_out_00 = '0' + report "selector=10 : data_out_00" + severity Error; + + assert data_out_01 = '0' + report "selector=10 : data_out_01" + severity Error; + + assert data_out_10 = '1' + report "selector=10 : data_out_10" + severity Error; + + assert data_out_11 = '0' + report "selector=10 : data_out_11" + severity Error; + + + -- selector = 11 + selector <= "11"; + + wait for period; + + assert data_out_00 = '0' + report "selector=11 : data_out_00" + severity Error; + + assert data_out_01 = '0' + report "selector=11 : data_out_01" + severity Error; + + assert data_out_10 = '0' + report "selector=11 : data_out_10" + severity Error; + + assert data_out_11 = '1' + report "selector=11 : data_out_11" + severity Error; + + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_alu.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_alu.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_alu.vhd (revision 10) @@ -0,0 +1,477 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_alu +-- +-- PURPOSE: testbench of scalar alu entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_alu is +end tb_alu; + +architecture testbench of tb_alu is + component alu + port( + a_in: in std_logic_vector(31 downto 0); + b_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + aluop: in std_logic_vector(3 downto 0); + op_select: in std_logic; + zero_out: out std_logic; + carry_out: out std_logic; + alu_out: out std_logic_vector(31 downto 0) + ); + end component; + + for impl: alu use entity work.alu(rtl); + + signal a_in: std_logic_vector(31 downto 0); + signal b_in: std_logic_vector(31 downto 0); + signal carry_in: std_logic; + signal aluop: std_logic_vector(3 downto 0); + signal op_select: std_logic := '0'; + signal carry_out: std_logic; + signal zero_out: std_logic; + signal alu_out: std_logic_vector(31 downto 0); + + constant period : time := 2ns; + + begin + impl: alu + port map ( + a_in => a_in, b_in => b_in, carry_in => carry_in, aluop => + aluop, op_select => op_select, carry_out => carry_out, + zero_out => zero_out, alu_out => alu_out); + + process + begin + + wait for 100ns; + + -- ############################################################### + + -- add 1: zero_out clear, carry_out_clear + a_in <= "10010000001000010000000001010101"; + b_in <= "01000010000000000001000100000010"; + carry_in <= '0'; + aluop <= "0000"; + + wait for period; + + assert alu_out = "11010010001000010001000101010111" + report "add 1 : alu_out" + severity Error; + + assert carry_out = '0' + report "add 1 : carry_out" + severity Error; + + assert zero_out = '0' + report "add 1 : zero_out" + severity Error; + + -- add 2: zero_out set, carry_out clear + a_in <= "00000000000000000000000000000000"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '0'; + aluop <= "0000"; + + wait for period; + + assert alu_out = "00000000000000000000000000000000" + report "add 2 : alu_out" + severity Error; + + assert carry_out = '0' + report "add 2 : carry_out" + severity Error; + + assert zero_out = '1' + report "add 2 : zero_out" + severity Error; + + + -- add 3: zero_out clear, carry_out set + a_in <= "11111111111111111111111111111111"; + b_in <= "11111111111111111111111111111111"; + carry_in <= '0'; + aluop <= "0000"; + + wait for period; + + assert alu_out = "11111111111111111111111111111110" + report "add 3 : alu_out" + severity Error; + + assert carry_out = '1' + report "add 3 : carry_out" + severity Error; + + assert zero_out = '0' + report "add 3 : zero_out" + severity Error; + + -- ############################################################### + + -- adc 1: carry_in set, zero_out clear, carry_out_clear + a_in <= "00000000000000000000000000000100"; + b_in <= "00000000000000000000000000000010"; + carry_in <= '1'; + aluop <= "0001"; + + wait for period; + + assert alu_out = "00000000000000000000000000000111" + report "adc 1 : alu_out" + severity Error; + + assert carry_out = '0' + report "adc 1 : carry_out" + severity Error; + + assert zero_out = '0' + report "adc 1 : zero_out" + severity Error; + + -- adc 2: carry_in clear, zero_out clear, carry_out_clear + a_in <= "00000000000000000000000000000100"; + b_in <= "00000000000000000000000000000010"; + carry_in <= '0'; + aluop <= "0001"; + + wait for period; + + assert alu_out = "00000000000000000000000000000110" + report "adc 2 : alu_out" + severity Error; + + assert carry_out = '0' + report "adc 2 : carry_out" + severity Error; + + assert zero_out = '0' + report "adc 2 : zero_out" + severity Error; + + -- ############################################################### + + -- sub 1: result positive, zero_out clear, carry_out clear + a_in <= "00000000000000000000000010101011"; + b_in <= "00000000000000000000000010100010"; + carry_in <= '0'; + aluop <= "0010"; + + wait for period; + + assert alu_out = "00000000000000000000000000001001" + report "sub 1 : alu_out" + severity Error; + + assert carry_out = '0' + report "sub 1 : carry_out" + severity Error; + + assert zero_out = '0' + report "sub 1 : zero_out" + severity Error; + + + -- sub 2: result negative, zero_out clear, carry_out set + a_in <= "00000000000000000000000000000000"; + b_in <= "00000000000000000000000000000001"; + carry_in <= '0'; + aluop <= "0010"; + + wait for period; + + assert alu_out = "11111111111111111111111111111111" + report "sub 2 : alu_out" + severity Error; + + assert carry_out = '1' + report "sub 2 : carry_out" + severity Error; + + assert zero_out = '0' + report "sub 2 : zero_out" + severity Error; + + -- ############################################################### + + -- sbc 1: carry_in set, result positive, zero_out clear, carry_out clear + a_in <= "00000000000000000000000010101011"; + b_in <= "00000000000000000000000010100010"; + carry_in <= '1'; + aluop <= "0011"; + + wait for period; + + assert alu_out = "00000000000000000000000000001000" + report "sub 1 : alu_out" + severity Error; + + assert carry_out = '0' + report "sub 1 : carry_out" + severity Error; + + assert zero_out = '0' + report "sub 1 : zero_out" + severity Error; + + -- sbc 2: carry_in clear, result positive, zero_out clear, carry_out clear + a_in <= "00000000000000000000000010101011"; + b_in <= "00000000000000000000000010100010"; + carry_in <= '0'; + aluop <= "0011"; + + wait for period; + + assert alu_out = "00000000000000000000000000001001" + report "sub 2 : alu_out" + severity Error; + + assert carry_out = '0' + report "sub 2 : carry_out" + severity Error; + + assert zero_out = '0' + report "sub2 : zero_out" + severity Error; + + -- ############################################################### + + -- inc: + a_in <= "00000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '0'; + aluop <= "0100"; + + wait for period; + + assert alu_out = "00000000000000000000000000000100" + report "inc : alu_out" + severity Error; + + assert carry_out = '0' + report "inc : carry_out" + severity Error; + + assert zero_out = '0' + report "inc : zero_out" + severity Error; + + -- ############################################################### + + -- dec: + a_in <= "00000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '0'; + aluop <= "0110"; + + wait for period; + + assert alu_out = "00000000000000000000000000000010" + report "dec : alu_out" + severity Error; + + assert carry_out = '0' + report "dec : carry_out" + severity Error; + + assert zero_out = '0' + report "dec : zero_out" + severity Error; + + + -- ############################################################### + + -- and: + a_in <= "11010000000000000000000000001011"; + b_in <= "10110000000000000000000000001101"; + carry_in <= '0'; + aluop <= "1000"; + + wait for period; + + assert alu_out = "10010000000000000000000000001001" + report "and : alu_out" + severity Error; + + assert carry_out = '0' + report "and : carry_out" + severity Error; + + assert zero_out = '0' + report "and : zero_out" + severity Error; + + -- ############################################################### + + -- or: + a_in <= "11010000000000000000000000001011"; + b_in <= "10110000000000000000000000001101"; + carry_in <= '0'; + aluop <= "1001"; + + wait for period; + + assert alu_out = "11110000000000000000000000001111" + report "or : alu_out" + severity Error; + + assert carry_out = '0' + report "or : carry_out" + severity Error; + + assert zero_out = '0' + report "or : zero_out" + severity Error; + + -- ############################################################### + + -- xor: + a_in <= "11010000000000000000000000001011"; + b_in <= "10110000000000000000000000001101"; + carry_in <= '0'; + aluop <= "1010"; + + wait for period; + + assert alu_out = "01100000000000000000000000000110" + report "xor : alu_out" + severity Error; + + assert carry_out = '0' + report "xor : carry_out" + severity Error; + + assert zero_out = '0' + report "xor : zero_out" + severity Error; + + -- ############################################################### + + -- lsl: + a_in <= "11000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '0'; + aluop <= "1100"; + + wait for period; + + assert alu_out = "10000000000000000000000000000110" + report "lsl : alu_out" + severity Error; + + assert carry_out = '1' + report "lsl : carry_out" + severity Error; + + assert zero_out = '0' + report "lsl : zero_out" + severity Error; + + -- ############################################################### + + -- lsr: + a_in <= "11000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '0'; + aluop <= "1110"; + + wait for period; + + assert alu_out = "01100000000000000000000000000001" + report "lsr : alu_out" + severity Error; + + assert carry_out = '1' + report "lsr : carry_out" + severity Error; + + assert zero_out = '0' + report "lsr : zero_out" + severity Error; + + + -- ############################################################### + + -- rol: carry_in set + a_in <= "11000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '1'; + aluop <= "1101"; + + wait for period; + + assert alu_out = "10000000000000000000000000000111" + report "rol : alu_out" + severity Error; + + assert carry_out = '1' + report "rol : carry_out" + severity Error; + + assert zero_out = '0' + report "rol : zero_out" + severity Error; + + -- ############################################################### + + -- ror: carry_in set + a_in <= "11000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '1'; + aluop <= "1111"; + + wait for period; + + assert alu_out = "11100000000000000000000000000001" + report "ror : alu_out" + severity Error; + + assert carry_out = '1' + report "ror : carry_out" + severity Error; + + assert zero_out = '0' + report "ror : zero_out" + severity Error; + + + -- ############################################################### + + op_select <= '1'; + + -- add: + a_in <= "11000000000000000000000000000011"; + b_in <= "00000000000000000000000000000000"; + carry_in <= '0'; + aluop <= "1111"; + + wait for period; + + assert alu_out = "11000000000000000000000000000011" + report "ror : alu_out" + severity Error; + + assert carry_out = '0' + report "ror : carry_out" + severity Error; + + assert zero_out = '0' + report "ror : zero_out" + severity Error; + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_instructioncounter.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_instructioncounter.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_instructioncounter.vhd (revision 10) @@ -0,0 +1,150 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_addressgroup +-- +-- PURPOSE: testbench of instruction counter entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_instructioncounter is +end tb_instructioncounter; + +architecture testbench of tb_instructioncounter is + component instructioncounter + port( clk: in std_logic; + load: in std_logic; + inc: in std_logic; + reset: in std_logic; + data_in: in std_logic_vector(31 downto 0); + data_out: out std_logic_vector(31 downto 0) + ); + end component; + + for impl: instructioncounter use entity work.instructioncounter(rtl); + + signal clk: std_logic; + signal load: std_logic; + signal inc: std_logic; + signal reset: std_logic := '0'; + signal data_in: std_logic_vector(31 downto 0); + signal data_out: std_logic_vector(31 downto 0); + + constant period : time := 2ns; + + begin + impl: instructioncounter port map (clk => clk, load => load, inc => inc, reset => reset, + data_in => data_in, data_out => data_out); + process + begin + wait for 100ns; + + -- load 1 + data_in <= "11001100110011001100110011001100"; + load <= '1'; + inc <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11001100110011001100110011001100" + report "load 1 : data_out" + severity Error; + + + -- load = inc = 0 + data_in <= "01010101010101010101010101010101"; + load <= '0'; + inc <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11001100110011001100110011001100" + report "load=inc=0: data_out" + severity Error; + + + -- load 2 + data_in <= "10101010101010101010101010101010"; + load <= '1'; + inc <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "10101010101010101010101010101010" + report "load 2 : data_out" + severity Error; + + + -- load = inc = 1 + data_in <= "01110001011100010111000101110001"; + load <= '1'; + inc <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "10101010101010101010101010101010" + report "load=inc=1 : data_out" + severity Error; + + + -- load 3 + data_in <= "11111111111111111111111111111110"; + load <= '1'; + inc <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11111111111111111111111111111110" + report "load 3 : data_out" + severity Error; + + -- inc + data_in <= "10101010101010101010101010101010"; + load <= '0'; + inc <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "11111111111111111111111111111111" + report "inc : data_out" + severity Error; + + + -- inc overflow + data_in <= "10101010101010101010101010101010"; + load <= '0'; + inc <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "00000000000000000000000000000000" + report "inc overflow: data_out" + severity Error; + + + -- reset + data_in <= "10101010101010101010101010101010"; + load <= '1'; + inc <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + reset <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = "00000000000000000000000000000000" + report "reset: data_out" + severity Error; + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_registergroup.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_registergroup.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_registergroup.vhd (revision 10) @@ -0,0 +1,145 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_registergroup +-- +-- PURPOSE: testbench of registergroup entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_registergroup is +end tb_registergroup; + +architecture testbench of tb_registergroup is + + component registergroup + port( clk: in std_logic; + result_in: in std_logic_vector(31 downto 0); + vector_in: in std_logic_vector(31 downto 0); + ic_in: in std_logic_vector(31 downto 0); + enable_in: in std_logic; + x_out: out std_logic_vector(31 downto 0); + y_out: out std_logic_vector(31 downto 0); + a_out: out std_logic_vector(31 downto 0); + sel_source: in std_logic_vector(1 downto 0); + sel_dest: in std_logic_vector(1 downto 0) + ); + end component; + + for impl: registergroup use entity work.registergroup(rtl); + + signal clk: std_logic; + signal result_in: std_logic_vector(31 downto 0); + signal vector_in: std_logic_vector(31 downto 0); + signal ic_in: std_logic_vector(31 downto 0); + signal enable_in: std_logic := '1'; + signal x_out: std_logic_vector(31 downto 0); + signal y_out: std_logic_vector(31 downto 0); + signal a_out: std_logic_vector(31 downto 0); + signal sel_source: std_logic_vector(1 downto 0); + signal sel_dest: std_logic_vector(1 downto 0); + + constant period : time := 2ns; + + begin + impl: registergroup port map (clk => clk, result_in => result_in, vector_in => vector_in, + ic_in => ic_in, enable_in => enable_in, x_out => x_out, y_out => y_out, a_out => a_out, + sel_source => sel_source, sel_dest => sel_dest); + process + begin + wait for 100ns; + + -- 1: load a from alu, store + result_in <= "10110011101100111011001110110011"; + sel_source <= "00"; + sel_dest <= "01"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + + assert a_out = "10110011101100111011001110110011" + report "1 : a_out_out" + severity Error; + + -- 2: load x from vector + vector_in <= "11100010111000101110001011100010"; + sel_source <= "10"; + sel_dest <= "10"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert a_out = "10110011101100111011001110110011" + report "2 : a_out_out" + severity Error; + + assert x_out = "11100010111000101110001011100010" + report "2 : x_out" + severity Error; + + -- 3: load nothing + sel_source <= "00"; + sel_dest <= "00"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + + assert a_out = "10110011101100111011001110110011" + report "3 : a_out_out" + severity Error; + + assert x_out = "11100010111000101110001011100010" + report "3 : x_out" + severity Error; + + + -- 4: load y from ic, store ic + result_in <= "10110011101100111011001110110011"; + ic_in <= "10010010110110100111010101101101"; + + sel_source <= "01"; + sel_dest <= "11"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert a_out = "10110011101100111011001110110011" + report "4 : a_out_out" + severity Error; + + assert x_out = "11100010111000101110001011100010" + report "4 : x_out" + severity Error; + + assert y_out = "10010010110110100111010101101101" + report "4 : y_out" + severity Error; + + -- 5: dont load y from alu (enable clear) + result_in <= "11110000111100001111000011110000"; + + enable_in <= '0'; + sel_source <= "00"; + sel_dest <= "11"; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert a_out = "10110011101100111011001110110011" + report "5 : a_out_out" + severity Error; + + assert x_out = "11100010111000101110001011100010" + report "5 : x_out" + severity Error; + + assert y_out = "10010010110110100111010101101101" + report "5 : y_out" + severity Error; + + wait; + end process; +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_addressgroup.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_addressgroup.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_addressgroup.vhd (revision 10) @@ -0,0 +1,120 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_addressgroup +-- +-- PURPOSE: testbench of addressgroup entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_addressgroup is +end tb_addressgroup; + +architecture testbench of tb_addressgroup is + component addressgroup + port( clk: in std_logic; + address_in: in std_logic_vector(31 downto 0); + address_out: out std_logic_vector(31 downto 0); + ic_out: out std_logic_vector(31 downto 0); + sel_source: in std_logic; + inc: in std_logic; + load_ic: in std_logic; + reset_ic: in std_logic + ); + end component; + + for impl: addressgroup use entity work.addressgroup(rtl); + + signal clk: std_logic; + signal address_in: std_logic_vector(31 downto 0); + signal address_out: std_logic_vector(31 downto 0); + signal ic_out: std_logic_vector(31 downto 0); + signal sel_source: std_logic; + signal inc: std_logic; + signal load_ic: std_logic; + signal reset_ic: std_logic := '0'; + + constant period : time := 2ns; + + begin + impl: addressgroup port map (clk => clk, address_in => address_in, address_out => address_out, + ic_out => ic_out, sel_source => sel_source, inc => inc, load_ic => load_ic, reset_ic => reset_ic); + process + begin + wait for 100ns; + + -- 1: load ic, use ic + address_in <= "11010011110100111101001111010011"; + load_ic <= '1'; + inc <= '0'; + sel_source <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ic_out = "11010011110100111101001111010011" + report "1 : ic_out" + severity Error; + + assert address_out = "11010011110100111101001111010011" + report "1 : address_out" + severity Error; + + -- 2: dont load ic, use address + address_in <= "00011110000111100001111000011110"; + load_ic <= '0'; + inc <= '0'; + sel_source <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ic_out = "11010011110100111101001111010011" + report "2 : ic_out" + severity Error; + + assert address_out = "00011110000111100001111000011110" + report "2 : address_out" + severity Error; + + -- 3: inc ic, use ic + address_in <= "00011110000111100001111000011110"; + load_ic <= '0'; + inc <= '1'; + sel_source <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ic_out = "11010011110100111101001111010100" + report "3 : ic_out" + severity Error; + + assert address_out = "11010011110100111101001111010100" + report "3 : address_out" + severity Error; + + -- 4: reset + address_in <= "00011110000111100001111000011110"; + load_ic <= '0'; + inc <= '0'; + sel_source <= '1'; + reset_ic <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert ic_out = "00000000000000000000000000000000" + report "4 : ic_out" + severity Error; + + assert address_out = "00011110000111100001111000011110" + report "4 : address_out" + severity Error; + + + wait; + end process; +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_system.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_system.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_system.vhd (revision 10) @@ -0,0 +1,62 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_system +-- +-- PURPOSE: testbench of system entity +-- top level simulation model !!! +-- requires debugging unit to be deactivated !!! +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_system is +end tb_system; + +architecture testbench of tb_system is + component system + port( + clk: in std_logic; + reset: in std_logic; + + rs232_txd: out std_logic; + rs232_rxd: in std_logic + ); + end component; + + for impl: system use entity work.system(rtl); + + signal clk: std_logic; + signal reset: std_logic; + signal rxd: std_logic; + signal txd: std_logic; + + constant period : time := 2ns; + +begin + + impl: system port map (clk => clk, reset => reset, rs232_txd => txd, rs232_rxd => rxd); + + process + begin + wait for 100ns; + + -- reset + reset <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + reset <= '0'; + + -- start + for i in 0 to 420000000 loop + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + end loop; + + wait; + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_flaggroup.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_flaggroup.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_flaggroup.vhd (revision 10) @@ -0,0 +1,129 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_flaggroup +-- +-- PURPOSE: testbench of flaggroup entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_flaggroup is +end tb_flaggroup; + +architecture testbench of tb_flaggroup is + component flaggroup + port( + clk: in std_logic; + c_in: in std_logic; + z_in: in std_logic; + c_out: out std_logic; + z_out: out std_logic; + load_c: in std_logic; + load_z: in std_logic; + sel_c: in std_logic_vector(1 downto 0); + sel_z: in std_logic_vector(1 downto 0) + ); + end component; + + for impl: flaggroup use entity work.flaggroup(rtl); + + signal clk: std_logic; + signal c_in: std_logic; + signal z_in: std_logic; + signal c_out: std_logic; + signal z_out: std_logic; + signal load_c: std_logic; + signal load_z: std_logic; + signal sel_c: std_logic_vector(1 downto 0); + signal sel_z: std_logic_vector(1 downto 0); + + constant period : time := 2ns; + + begin + impl: flaggroup port map (clk => clk, c_in => c_in, z_in => z_in, c_out => c_out, + z_out => z_out, load_c => load_c, load_z => load_z, sel_c => sel_c, sel_z => sel_z); + process + begin + wait for 100ns; + + -- set c, clear z + sel_c <= "11"; + sel_z <= "10"; + load_c <= '1'; + load_z <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert c_out = '1' + report "set c, clear z : c_out" + severity Error; + + assert z_out = '0' + report "set c, clear z : z_out" + severity Error; + + -- clear c, set z + sel_c <= "10"; + sel_z <= "11"; + load_c <= '1'; + load_z <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert c_out = '0' + report "clear c, set z : c_out" + severity Error; + + assert z_out = '1' + report "clear c, set z : z_out" + severity Error; + + + -- load c, read z + c_in <= '1'; + z_in <= '0'; + + sel_c <= "00"; + sel_z <= "00"; + load_c <= '1'; + load_z <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert c_out = '1' + report "load c, read z : c_out" + severity Error; + + assert z_out = '1' + report "load c, read z : z_out" + severity Error; + + + -- read c, load z + c_in <= '0'; + z_in <= '0'; + + sel_c <= "00"; + sel_z <= "00"; + load_c <= '0'; + load_z <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert c_out = '1' + report "read c, load z : c_out" + severity Error; + + assert z_out = '0' + report "read c, load z : z_out" + severity Error; + + wait; + end process; +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_vector_register.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_vector_register.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_vector_register.vhd (revision 10) @@ -0,0 +1,197 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_vector_register +-- +-- PURPOSE: testbench of vector_register entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_vector_register is +end tb_vector_register; + +architecture testbench of tb_vector_register is + component vector_register + generic ( + n : integer range 1 to 256; + slicenr : natural + ); + + port ( + clk: in std_logic; + r_in: in std_logic_vector(31 downto 0); + v_out: out std_logic_vector(31 downto 0); + w_out: out std_logic_vector(31 downto 0); + load_r: in std_logic; + load_select: in std_logic; + k_in: in std_logic_vector(31 downto 0); + select_v: in std_logic_vector(7 downto 0); + select_w: in std_logic_vector(2 downto 0); + select_r: in std_logic_vector(7 downto 0) + ); + end component; + + for impl: vector_register use entity work.vector_register(rtl); + + constant n: integer range 0 to 256 := 4; + constant slicenr: natural := 2; + + signal clk: std_logic; + signal r_in: std_logic_vector(31 downto 0); + signal v_out: std_logic_vector(31 downto 0); + signal w_out: std_logic_vector(31 downto 0); + signal k_in: std_logic_vector(31 downto 0); + signal load_r: std_logic; + signal load_select: std_logic; + signal select_v: std_logic_vector(7 downto 0) := "00000000"; + signal select_w: std_logic_vector(2 downto 0) := "000"; + signal select_r: std_logic_vector(7 downto 0) := "00000000"; + + constant period : time := 2ns; + + begin + impl: vector_register generic map (n => n, slicenr => slicenr) + port map (clk => clk, r_in => r_in, v_out => v_out, w_out => w_out, + load_r => load_r, load_select => load_select, k_in => k_in, select_v => + select_v, select_w => select_w, select_r => select_r); + + process + begin + + wait for 100ns; + + -- 1: load 00000000, v_out = 00000000, w_out = 00000000 + + r_in <= "11010010110111101101001011011110"; + select_r <= "00000000"; + select_v <= "00000000"; + select_w <= "000"; + load_r <= '1'; + load_select <= '0'; + + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert v_out = "11010010110111101101001011011110" + report "1 : v_out" + severity Error; + + assert w_out = "11010010110111101101001011011110" + report "1 : w_out" + severity Error; + + + -- 2: load 00000001, v_out = 00000000, w_out = 00000001 + + r_in <= "10010011001110101001001100111010"; + select_r <= "00000001"; + select_v <= "00000000"; + select_w <= "001"; + load_r <= '1'; + load_select <= '0'; + + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert v_out = "11010010110111101101001011011110" + report "2 : v_out" + severity Error; + + assert w_out = "10010011001110101001001100111010" + report "2 : w_out" + severity Error; + + + -- 3: load 00000010, v_out = 00000010, w_out = 00000000 + + r_in <= "11110001110000111111000111000011"; + select_r <= "00000010"; + select_v <= "00000010"; + select_w <= "000"; + load_r <= '1'; + load_select <= '0'; + + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert v_out = "11110001110000111111000111000011" + report "3 : v_out" + severity Error; + + assert w_out = "11010010110111101101001011011110" + report "3 : w_out" + severity Error; + + -- 4: load 00000011, v_out = 00000000, w_out = 00000010 + + r_in <= "00011110000111100001111000011110"; + select_r <= "00000011"; + select_v <= "00000000"; + select_w <= "010"; + load_r <= '1'; + load_select <= '0'; + + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert v_out = "11010010110111101101001011011110" + report "4 : v_out" + severity Error; + + assert w_out = "11110001110000111111000111000011" + report "4 : w_out" + severity Error; + + -- 5: load 00000000, set slicenr wrong + + r_in <= "11111111000000001111111100000000"; + select_r <= "00000000"; + select_v <= "00000000"; + select_w <= "010"; + k_in <= "00000000000000000000000000000000"; + load_r <= '1'; + load_select <= '1'; + + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert v_out = "11010010110111101101001011011110" + report "5 : v_out" + severity Error; + + assert w_out = "11110001110000111111000111000011" + report "5 : w_out" + severity Error; + + + -- 6: load 00000000, set slicenr properly + + r_in <= "11111111000000001111111100000000"; + select_r <= "00000000"; + select_v <= "00000000"; + select_w <= "010"; + k_in <= "00000000000000000000000000000010"; + load_r <= '1'; + load_select <= '1'; + + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert v_out = "11111111000000001111111100000000" + report "6 : v_out" + severity Error; + + assert w_out = "11110001110000111111000111000011" + report "6 : w_out" + severity Error; + + wait; + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_vector_alu_32.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_vector_alu_32.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_vector_alu_32.vhd (revision 10) @@ -0,0 +1,553 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_vector_alu_32 +-- +-- PURPOSE: testbench of vector_alu_32 entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_vector_alu_32 is +end tb_vector_alu_32; + +architecture testbench of tb_vector_alu_32 is + component vector_alu_32 + port ( + clk: in std_logic; + v_in: in std_logic_vector(31 downto 0); + w_in: in std_logic_vector(31 downto 0); + carry_in: in std_logic; + rshift_in: in std_logic; + carry_out: out std_logic; + valu_out: out std_logic_vector(31 downto 0); + valuop: in std_logic_vector(3 downto 0); + source_sel: in std_logic_vector(1 downto 0); + carry_sel: in std_logic_vector(1 downto 0); + mult_source_sel: in std_logic_vector(1 downto 0); + mult_dest_sel: in std_logic_vector(1 downto 0); + reg_input_sel: in std_logic; + load_lsr: in std_logic; + load_other: in std_logic + ); + end component; + + component valu_controlunit + port( + clk: in std_logic; + valu_go: in std_logic; + valuop: in std_logic_vector(3 downto 0); + vwidth: in std_logic_vector(1 downto 0); + source_sel: out std_logic_vector(1 downto 0); + carry_sel: out std_logic_vector(1 downto 0); + mult_source_sel: out std_logic_vector(1 downto 0); + mult_dest_sel: out std_logic_vector(1 downto 0); + reg_input_sel: out std_logic; + load_lsr: out std_logic; + load_other: out std_logic; + out_valid: out std_logic + ); + end component; + + for valu_controlunit_impl: valu_controlunit use entity work.valu_controlunit(rtl); + for alu_impl: vector_alu_32 use entity work.vector_alu_32(rtl); + + signal clk: std_logic; + signal valu_go: std_logic; + signal vwidth: std_logic_vector(1 downto 0); + signal out_valid: std_logic; + signal v_in: std_logic_vector(31 downto 0); + signal w_in: std_logic_vector(31 downto 0); + signal carry_in: std_logic; + signal rshift_in: std_logic; + signal carry_out: std_logic; + signal valu_out: std_logic_vector(31 downto 0); + signal valuop: std_logic_vector(3 downto 0); + signal source_sel: std_logic_vector(1 downto 0); + signal carry_sel: std_logic_vector(1 downto 0); + signal load_lsr: std_logic; + signal load_other: std_logic; + signal mult_source_sel: std_logic_vector(1 downto 0); + signal mult_dest_sel: std_logic_vector(1 downto 0); + signal reg_input_sel: std_logic := '0'; + + constant period : time := 2ns; + + begin + valu_controlunit_impl: valu_controlunit + port map ( + clk => clk, + valu_go => valu_go, + valuop => valuop, + vwidth => vwidth, + source_sel => source_sel, + carry_sel => carry_sel, + mult_source_sel => mult_source_sel, + mult_dest_sel => mult_dest_sel, + reg_input_sel => reg_input_sel, + load_lsr => load_lsr, + load_other => load_other, + out_valid => out_valid + ); + + alu_impl: vector_alu_32 + port map ( + clk => clk, + v_in => v_in, + w_in => w_in, + carry_in => carry_in, + rshift_in => rshift_in, + carry_out => carry_out, + valu_out => valu_out, + valuop => valuop, + source_sel => source_sel, + carry_sel => carry_sel, + mult_source_sel => mult_source_sel, + mult_dest_sel => mult_dest_sel, + reg_input_sel => reg_input_sel, + load_lsr => load_lsr, + load_other => load_other + ); + + process + begin + + wait for 100ns; + + -- vadd 8_bit + v_in <= x"FE5A3415"; + w_in <= x"3EBB6849"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "0000"; + vwidth <= "00"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + + assert valu_out = x"3C159C5E" + report "vadd 8_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vadd 8_bit : carry_out" + severity Error; + + + -- vadd 16_bit + v_in <= x"F0A17E63"; + w_in <= x"09C4A185"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "0000"; + vwidth <= "01"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + + assert valu_out = x"FA651FE8" + report "vadd 16_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vadd 16_bit : carry_out" + severity Error; + + + -- vadd 32_bit + v_in <= x"F0A17E63"; + w_in <= x"09C4A185"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "0000"; + vwidth <= "10"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = x"FA661FE8" + report "vadd 32_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vadd 32_bit : carry_out" + severity Error; + + -- vadd 64_bit + v_in <= x"F0A17E63"; + w_in <= x"09C4A185"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "0000"; + vwidth <= "11"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = x"FA661FE9" + report "vadd 64_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vadd 64_bit : carry_out" + severity Error; + + + -- vand 8_bit + v_in <= "10010100110110101110010011101011"; + w_in <= "11010110101101010101010101010110"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1000"; + vwidth <= "00"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "10010100100100000100010001000010" + report "vand 8_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vand 8_bit : carry_out" + severity Error; + + -- vand 16_bit + v_in <= "10010100110110101110010011101011"; + w_in <= "11010110101101010101010101010110"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1000"; + vwidth <= "01"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "10010100100100000100010001000010" + report "vand 16_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vand 16_bit : carry_out" + severity Error; + + -- vand 32_bit + v_in <= "10010100110110101110010011101011"; + w_in <= "11010110101101010101010101010110"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1000"; + vwidth <= "10"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "10010100100100000100010001000010" + report "vand 32_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vand 32_bit : carry_out" + severity Error; + + -- vand 64_bit + v_in <= "10010100110110101110010011101011"; + w_in <= "11010110101101010101010101010110"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1000"; + vwidth <= "11"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "10010100100100000100010001000010" + report "vand 64_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vand 64_bit : carry_out" + severity Error; + + + -- vlsl 8_bit + v_in <= "10010101001100100101101110111011"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1100"; + vwidth <= "00"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "00101010011001001011011001110110" + report "vlsl 8_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vlsl 8_bit : carry_out" + severity Error; + + + -- vlsl 16_bit + v_in <= "10010101001100100101101110111011"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1100"; + vwidth <= "01"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "00101010011001001011011101110110" + report "vlsl 16_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vlsl 16_bit : carry_out" + severity Error; + + -- vlsl 32_bit + v_in <= "10010101001100100101101110111011"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1100"; + vwidth <= "10"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "00101010011001001011011101110110" + report "vlsl 32_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vlsl 32_bit : carry_out" + severity Error; + + -- vlsl 64_bit + v_in <= "10010101001100100101101110111011"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1100"; + vwidth <= "11"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "00101010011001001011011101110111" + report "vlsl 64_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vlsl 64_bit : carry_out" + severity Error; + + + -- vlsr 8_bit + v_in <= "10010101001100100101101110111011"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '0'; + valuop <= "1110"; + vwidth <= "00"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "01001010000110010010110101011101" + report "vlsr 8_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vlsr 8_bit : carry_out" + severity Error; + + + -- vlsr 16_bit + v_in <= "10010111011010110100100110010010"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '1'; + valuop <= "1110"; + vwidth <= "01"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "01001011101101010010010011001001" + report "vlsr 16_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vlsr 16_bit : carry_out" + severity Error; + + + -- vlsr 32_bit + v_in <= "11001010110101011011111110110111"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '1'; + valuop <= "1110"; + vwidth <= "10"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "01100101011010101101111111011011" + report "vlsr 32_bit : valu_out" + severity Error; + + assert carry_out = '1' + report "vlsr 32_bit : carry_out" + severity Error; + + -- vlsr 64_bit + v_in <= "00101010010110101010101001110110"; + w_in <= "11111111111111111111111111111111"; + + carry_in <= '1'; + rshift_in <= '1'; + valuop <= "1110"; + vwidth <= "11"; + + valu_go <= '1'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + valu_go <= '0'; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert valu_out = "10010101001011010101010100111011" + report "vlsr 64_bit : valu_out" + severity Error; + + assert carry_out = '0' + report "vlsr 64_bit : carry_out" + severity Error; + + wait; + + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/testbenches/tb_flag.vhd =================================================================== --- tags/arelease/cpu/testbenches/tb_flag.vhd (nonexistent) +++ tags/arelease/cpu/testbenches/tb_flag.vhd (revision 10) @@ -0,0 +1,81 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: tb_flag +-- +-- PURPOSE: testbench of flag entity +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +----------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity tb_flag is +end tb_flag; + +architecture testbench of tb_flag is + component flag + port( clk: in std_logic; + load: in std_logic; + data_in: in std_logic; + data_out: out std_logic + ); + end component; + + for impl: flag use entity work.flag(rtl); + + signal clk: std_logic; + signal load: std_logic; + signal data_in: std_logic; + signal data_out: std_logic; + + constant period : time := 2ns; + + begin + impl: flag port map (clk => clk, load => load, data_in => data_in, data_out => data_out); + process + begin + wait for 100ns; + + + -- load 1 + data_in <= '1'; + load <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = '1' + report "load 1 : data_out" + severity Error; + + + -- not load + data_in <= '0'; + load <= '0'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = '1' + report "not load : data_out" + severity Error; + + + -- load 2 + data_in <= '0'; + load <= '1'; + + clk <= '0'; wait for period / 2; clk <= '1'; wait for period / 2; + + assert data_out = '0' + report "load 2 : data_out" + severity Error; + + + wait; + + end process; + +end; \ No newline at end of file Index: tags/arelease/cpu/datatypes.vhd =================================================================== --- tags/arelease/cpu/datatypes.vhd (nonexistent) +++ tags/arelease/cpu/datatypes.vhd (revision 10) @@ -0,0 +1,22 @@ +------------------------------------------------------------------ +-- PROJECT: HiCoVec (highly configurable vector processor) +-- +-- ENTITY: datatypes +-- +-- PURPOSE: definition of basic datatype +-- +-- AUTHOR: harald manske, haraldmanske@gmx.de +-- +-- VERSION: 1.0 +------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.cfg.all; + +package datatypes is + type vectordata_type is array (k-1 downto 0) of std_logic_vector(31 downto 0); +end datatypes; + Index: tags/arelease/cpu/constraints.ucf =================================================================== --- tags/arelease/cpu/constraints.ucf (nonexistent) +++ tags/arelease/cpu/constraints.ucf (revision 10) @@ -0,0 +1,8 @@ +NET "clk" PERIOD = 20.0ns HIGH 40%; +NET "clk" LOC = "E12"| IOSTANDARD = LVCMOS33; + +NET "rs232_rxd" LOC = "E16" | IOSTANDARD = LVTTL ; +NET "rs232_txd" LOC = "F15" | IOSTANDARD = LVTTL | DRIVE = 4 | SLEW = SLOW ; + +NET "reset" LOC = "U15" | IOSTANDARD = LVTTL | PULLDOWN ; + Index: tags/arelease/assembler/cputest.txt =================================================================== --- tags/arelease/assembler/cputest.txt (nonexistent) +++ tags/arelease/assembler/cputest.txt (revision 10) @@ -0,0 +1,1645 @@ +; ************************************************************************ +; * CPU validation program * +; ************************************************************************ +; * Executes all possible commands of the target cpu to be sure that it * +; * works properly. * +; * * +; * If an error occurs, the processor will run into a halt command. * +; * Otherwise it will continue execution to the finish symbol and loop * +; * there infinety * +; * * +; ************************************************************************ +; * Author: Harald Manske, haraldmanske@gmx.de * +; * Version: 1.0 * +; * Plattform: HiCoVec (highly configurable vector processor) * +; ************************************************************************ + +; configuration of the program + EQU n 8 ;requires n >= 4 + EQU k 20 ;requires k = 16 + EQU use_shuffle 0 ;requires shuffle unit + EQU use_mul 0 ;requires both, scalar and vector multiplicate + EQU use_vmolr 0 ;requires vmol and vmor commands (32 bit width) + + JMP 0+START + HALT + + +;test data + ORG $10 +DATA_V: DC $B2D463BC ; vector input data (max k=32) +DATA_V2: DC $AA67Df42 + DC $A3B78EF3 + DC $4E6AC974 + DC $8FEE432E + DC $FF3AB876 + DC $43B57621 + DC $8E6AC974 ;8 + DC $7FF3ACD3 + DC $921BC4D1 + DC $637DCF67 + DC $7897AABD + DC $973EE234 + DC $005C6E39 + DC $A1BC7A35 + DC $7FF8334E ;16 + DC $A3486CDF + DC $94CA193B + DC $445E97C1 + DC $8836D35E + DC $A9B2C45F + DC $97A36BFF + DC $79835987 + DC $DCBEDFEA + DC $975CC213 + DC $39DA322B + DC $8411DEA9 + DC $FFFFFFFF + DC $129DE3AF + DC $7881D74A + DC $AA8D35A8 + DC $5247877D + +V_RES: ORG $30 ; vector result data (max k=32) + + ORG $50 +MASK_HW: DC $FFFF0000 ; mask to get only high word +CMP_VAL: DC $ABCD ; value to compare with immediate +CMP_VAL2: DC $FEDC ; value to compare with immediate +DATA_A: DC $A3BF74E5 ; operand A +DATA_B: DC $03C7A483 ; operand B +DATA_FF: DC $FFFFFFFF ; operand FF +STORE_DEST: DC $0 ; destination for store command + +;results +AND_RES: DC $3872481 ; result: A and B +OR_RES: DC $A3FFF4E7 ; result: A or B +XOR_RES: DC $A078D066 ; result: A xor B +ADD_RES: DC $A7871968 ; result: A + B +SUB_RES: DC $9FF7D062 ; result: A - B +INC_RES: DC $A3BF74E6 ; result: A + 1 +DEC_RES: DC $A3BF74E4 ; result: A - 1 +LSL_RES: DC $477EE9CA ; result: lsl A +LSR_RES: DC $51DFBA72 ; result: lsr A +MUL_RES: DC $4B1E852F ; result A * B (16bit * 16bit) + +ROL_RES: DC $477EE9CA ; result: rol A, carry not set +ROL_RES_C: DC $477EE9CB ; result: rol A, carry set + +ROR_RES: DC $51DFBA72 +ROR_RES_C: DC $D1DFBA72 ; result: ror A, carry set + +RES_VSHUF_8L: DC $8EF3AA67 ; result: shuffle vwidth=00 low word +RES_VSHUF_8H: DC $DF42B2D4 ; result: shuffle vwidth=00 high word + +;program start +START: NOP + +;test flag commands and conditional jumps +TEST_ZERO: SEZ + JZ 0+TEST_NOTZERO + HALT +TEST_NOTZERO: CLZ + JZ 0+ERR_SCALAR + JNZ 0+TEST_CARRY + HALT +TEST_CARRY: SEC + JC 0+TEST_NOTCARRY + HALT +TEST_NOTCARRY: CLC + JC 0+ERR_SCALAR + JNC 0+TEST_FLAGS + HALT +TEST_FLAGS: SUB 0,0,1 + JZ 0+ERR_SCALAR + JNC 0+ERR_SCALAR + JNZ 0+TEST_FLAGS2 + HALT + TEST_FLAGS2: ADD 0,0,0 + JC 0+ERR_SCALAR + JZ 0+TEST_LD + HALT + +;test load operation +TEST_LD: LD A,0+CMP_VAL + JZ 0+ERR_SCALAR + SUB X,A,$ABCD + JC 0+ERR_SCALAR + JZ 0+TEST_LD2 + HALT + TEST_LD2: OR Y,0,CMP_VAL + OR X,0,1 + LD Y,Y+X + SUB 0,Y,$FEDC + JNZ 0+ERR_SCALAR + JZ 0+TEST_STORE + HALT + +;test store operation +TEST_STORE: LD X,0+DATA_A + LD Y,0+DATA_B + ADD A,X,Y + ST 0+STORE_DEST,A + LD X,0+ADD_RES + LD Y,0+STORE_DEST + SUB 0,X,Y + JZ 0+TEST_STORE2 + HALT + TEST_STORE2: OR A,0,$1234 + OR X,0,1 + OR Y,0,STORE_DEST + DEC Y,Y + ST X+Y,A + OR X,0,0 + LD X,0+STORE_DEST + SUB Y,X,$1234 + JNZ 0+ERR_SCALAR + +;test arithmetic and logic operations +TEST_ADD: LD X,0+DATA_A + LD Y,0+DATA_B + ADD A,X,Y + JC 0+ERR_SCALAR + JZ 0+ERR_SCALAR + LD Y,0+ADD_RES + SUB 0,A,Y + JNZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + LD X, 0+DATA_FF + ADD A,X,2 + JNC 0+ERR_SCALAR + JZ 0+ERR_SCALAR + SUB 0,A,1 + JZ 0+TEST_ADC + HALT + +TEST_ADC: LD A,0+DATA_A + LD X,0+DATA_B + CLC + ADC Y,A,X + JZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + LD A,0+ADD_RES + SUB 0,A,Y + JNZ 0+ERR_SCALAR + + LD Y,0+DATA_A + LD X,0+DATA_B + SEC + ADC A,X,Y + JZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + SUB A,A,1 + LD Y,0+ADD_RES + SUB 0,A,Y + JNZ 0+ERR_SCALAR + JNC 0+TEST_SUB + HALT + +TEST_SUB: LD X,0+DATA_A + LD Y,0+DATA_B + SUB A,X,Y + JC 0+ERR_SCALAR + LD X,0+SUB_RES + SUB 0,A,X + JNZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + LD X,0+DATA_A + SUB A,Y,X + JNC 0+ERR_SCALAR + JNZ 0+TEST_SBC + HALT + +TEST_SBC: LD A,0+DATA_A + LD Y,0+DATA_B + CLC + SUB X,A,Y + SBC A,A,Y + JZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + SUB 0,X,A + JNZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + LD A,0+DATA_A + SEC + SBC A,A,Y + JZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + SUB X,X,1 + SUB 0,A,X + JC 0+ERR_SCALAR + JZ 0+TEST_INC + HALT + +TEST_INC: LD A,0+DATA_A + INC A,A + LD X,0+INC_RES + LD Y,0+DATA_A + ADD Y,Y,1 + SUB 0,A,X + JNZ 0+ERR_SCALAR + SUB 0,A,Y + JNZ 0+ERR_SCALAR + LD A,0+DATA_FF + INC A,A + JNC 0+ERR_SCALAR + JZ 0+TEST_DEC + HALT + +TEST_DEC: OR A,0,0 + DEC A,A + JNC 0+ERR_SCALAR + JZ 0+ERR_SCALAR + LD X,0+DATA_FF + SUB 0,A,X + JNZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + LD A,0+DATA_A + DEC A,A + LD Y,0+DEC_RES + SUB 0,A,Y + JC 0+ERR_SCALAR + JZ 0+TEST_AND + HALT + +TEST_AND: LD A,0+DATA_A + LD X,0+DATA_B + AND Y,A,X + LD A,0+AND_RES + SUB 0,Y,A + JC 0+ERR_SCALAR + JNZ 0+ERR_SCALAR + LD A,0+DATA_FF + AND X,Y,A + SUB 0,Y,X + JNZ 0+ERR_SCALAR + OR Y,0,$3456 + AND Y,Y,0 + JZ 0+TEST_OR + HALT + +TEST_OR: LD X,0+DATA_A + LD Y,0+DATA_B + OR A,X,Y + LD X,0+OR_RES + JZ 0+ERR_SCALAR + SUB 0,A,X + JNZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + OR A,A,$FF + AND A,A,$FF + SUB 0,A,$FF + JC 0+ERR_SCALAR + JZ 0+TEST_XOR + HALT + +TEST_XOR: LD X,0+DATA_A + LD Y,0+DATA_B + XOR A,X,Y + LD X,0+XOR_RES + SUB 0,A,X + JC 0+ERR_SCALAR + JNZ 0+ERR_SCALAR + LD Y,0+ADD_RES + XOR A,A,Y + SUB 0,A,X + JZ 0+ERR_SCALAR + XOR A,A,Y + SUB 0,A,X + JZ 0+TEST_LSL + HALT + +TEST_LSL: LD A,0+DATA_A + LSL A,A + JNC 0+ERR_SCALAR + LD X,0+LSL_RES + SUB 0,A,X + JC 0+ERR_SCALAR + JZ 0+TEST_LSR + HALT + + +TEST_LSR: LD A,0+DATA_A + LSR A,A + JNC 0+ERR_SCALAR + LD X,0+LSR_RES + SUB 0,X,A + JC 0+ERR_SCALAR + JZ 0+TEST_ROL + HALT + +TEST_ROL: CLC + LD Y,0+DATA_A + ROL A,Y + JNC 0+ERR_SCALAR + LD X,0+ROL_RES + SUB 0,A,X + JC 0+ERR_SCALAR + JNZ 0+ERR_SCALAR + SEC + LD Y,0+DATA_A + ROL A,Y + JNC 0+ERR_SCALAR + LD X,0+ROL_RES_C + SUB 0,A,X + JC 0+ERR_SCALAR + JZ 0+TEST_ROR + HALT + +TEST_ROR: CLC + LD Y,0+DATA_A + ROR A,Y + JNC 0+ERR_SCALAR + LD X,0+ROR_RES + SUB 0,A,X + JC 0+ERR_SCALAR + JNZ 0+ERR_SCALAR + SEC + LD A,0+DATA_A + ROR A,A + JNC 0+ERR_SCALAR + LD X,0+ROR_RES_C + SUB 0,A,X + JC 0+ERR_SCALAR + JZ 0+TEST_JAL + HALT + +TEST_JAL: JAL A,0+TEST_JAL2 + HALT + TEST_JAL2: SUB 0,A,TEST_JAL + JNZ 0+ERR_SCALAR + JZ 0+TEST_MUL + +TEST_MUL: OR A,0,use_mul + JZ 0+NO_MUL + LD X,0+DATA_A + LD Y,0+DATA_B + MUL A,X,Y + JC 0+ERR_SCALAR + JZ 0+ERR_SCALAR + LD Y,0+MUL_RES + SUB 0,A,Y + JNZ 0+ERR_SCALAR + JC 0+ERR_SCALAR + NO_MUL: JMP 0+TEST_VLD_ST + +;test cooperative commands +TEST_VLD_ST: OR A,0,0 + OR Y,0,0 + VLD_ST_INIT: ST 0+V_RES,A ;init with 0 + INC Y,Y + SUB 0,Y,k + JNZ 0+VLD_ST_INIT + + OR A,0,DATA_V ;load + VLD R0,0+A + + OR A,0,V_RES + VST 0+A,R0 ;store + + OR Y,0,0 + VLD_ST_LOOP: LD A,Y+V_RES ;check + LD X,Y+DATA_V + SUB 0,A,X + JNZ 0+ERR_COOP + INC Y,Y + SUB 0,Y,k + JNZ 0+VLD_ST_LOOP + JMP 0+TEST_MOV + HALT + +TEST_MOV: OR A,0,0 + MOV_LOOP: LD Y,A+DATA_V + MOV R1(A),Y ;scalar => vector + INC A,A + SUB 0,A,k + JNZ 0+MOV_LOOP + + OR A,0,0 + OR X,0,0 + MOV_LOOP2: MOV X,R1(A) ;vector => scalar + LD Y,A+DATA_V + SUB 0,Y,X + JNZ 0+ERR_COOP + INC A,A + SUB 0,A,k + JNZ 0+MOV_LOOP2 + JZ 0+TEST_VMOV + HALT + +;test vector commands +TEST_VMOV: VMOV R0,R1 + VMOV R<2>,R0 + VMOV R3,R<2> + + OR A,0,0 + VMOV_LOOP: LD Y,A+DATA_V + + MOV X,R0(A) + SUB 0,Y,X + JNZ 0+ERR_VECTOR + + MOV X,R2(A) + SUB 0,Y,X + JNZ 0+ERR_VECTOR + + MOV X,R3(A) + SUB 0,Y,X + JNZ 0+ERR_VECTOR + + INC A,A + SUB 0,A,k + JNZ 0+VMOV_LOOP + +TEST_MOVA: LD A,0+DATA_A + MOVA R0,A + OR X,0,V_RES + VST 0+X,R0 + + OR X,0,0 + MOVA_LOOP: LD Y,X+V_RES + SUB 0,Y,A + JNZ 0+ERR_COOP + INC X,X + SUB 0,X,k + JNZ 0+MOVA_LOOP + +;test vector alu commands + OR A,0,DATA_V + VLD R0,0+A + OR A,0,DATA_V2 + VLD R1,0+A + +TEST_VAND: VAND.DW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VAND_LOOP: LD X,A+DATA_V + LD Y,A+DATA_V2 + AND X,X,Y + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VAND_LOOP + +TEST_VOR: VOR.DW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VOR_LOOP: LD X,A+DATA_V + LD Y,A+DATA_V2 + OR X,X,Y + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VOR_LOOP + +TEST_VXOR: VXOR.DW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VXOR_LOOP: LD X,A+DATA_V + LD Y,A+DATA_V2 + XOR X,X,Y + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VXOR_LOOP + +TEST_VADD: VADD.DW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + ;32 bit + OR A,0,0 + VADD_LOOP_DW: LD X,A+DATA_V + LD Y,A+DATA_V2 + ADD X,X,Y + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VADD_LOOP_DW + + ;64 bit + VADD.QW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VADD_LOOP_QW: ST 0+AKKU,A ;reset carry + OR A,0,0 + ST 0+CARRY,A + LD A,0+AKKU + + LD X,A+DATA_V + LD Y,A+DATA_V2 + ADD X,X,Y + + JNC 0+VADD_QW_NC ; save carry + ST 0+AKKU,A + OR A,0,1 + ST 0+CARRY,A + LD A,0+AKKU + + VADD_QW_NC: LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + + LD X,A+DATA_V + LD Y,A+DATA_V2 + ADD X,X,Y + LD Y,0+CARRY + ADD X,X,Y + LD Y,A+V_RES + + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + + SUB 0,A,k + JNZ 0+VADD_LOOP_QW + + ;16bit + VADD.W R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VADD_LOOP_W: LD X,A+DATA_V ;low word + LD Y,A+DATA_V2 + ADD X,X,Y + LD Y,A+V_RES + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + LD X,A+DATA_V ;high word + LD Y,0+MASK_HW + AND X,X,Y + + LD Y,A+DATA_V2 + ST 0+AKKU,A + LD A,0+MASK_HW + + AND Y,Y,A + + LD A,0+AKKU + + ADD X,X,Y + LD Y,A+V_RES + + ST 0+AKKU,A + OR A,0,0 + + VADD_LOOP_W2: LSR X,X + LSR Y,Y + INC A,A + SUB 0,A,16 + JNZ 0+VADD_LOOP_W2 + + LD A,0+AKKU + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + INC A,A + SUB 0,A,k + JNZ 0+VADD_LOOP_W + + ;8 bit + VADD.B R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VADD_LOOP_B: OR X,A,0 + ST 0+AKKU,A + LD A,X+DATA_V + ST 0+A_REG,A + LD A,X+DATA_V2 + ST 0+B_REG,A + LD A,X+V_RES + ST 0+RES_REG,A + OR A,0,0 + + VADD_LOOP_B2: ST 0+I,A + + LD X,0+A_REG + LD Y,0+B_REG + LD A,0+RES_REG + + ADD X,X,Y + AND X,X,$FF + AND A,A,$FF + + SUB 0,X,A + JNZ 0+ERR_VALU + + LD X,0+A_REG + LD Y,0+B_REG + LD A,0+RES_REG + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + ST 0+RES_REG,A + OR A,0,X + ST 0+A_REG,A + OR A,0,Y + ST 0+B_REG,A + + LD A,0+I + INC A,A + SUB 0,A,4 + JNZ 0+VADD_LOOP_B2 + + LD A,0+AKKU + INC A,A + SUB 0,A,k + JNZ 0+VADD_LOOP_B + +TEST_VSUB: VSUB.DW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + ;32 bit + OR A,0,0 + VSUB_LOOP_DW: LD X,A+DATA_V + LD Y,A+DATA_V2 + SUB X,X,Y + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VSUB_LOOP_DW + + ;64 bit + VSUB.QW R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VSUB_LOOP_QW: ST 0+AKKU,A ;reset carry + OR A,0,0 + ST 0+CARRY,A + LD A,0+AKKU + + LD X,A+DATA_V + LD Y,A+DATA_V2 + SUB X,X,Y + + JNC 0+VSUB_QW_NC ; save carry + ST 0+AKKU,A + OR A,0,1 + ST 0+CARRY,A + LD A,0+AKKU + + VSUB_QW_NC: LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + + LD X,A+DATA_V + LD Y,A+DATA_V2 + SUB X,X,Y + LD Y,0+CARRY + SUB X,X,Y + LD Y,A+V_RES + + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + + SUB 0,A,k + JNZ 0+VSUB_LOOP_QW + + ;16bit + VSUB.W R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VSUB_LOOP_W: LD X,A+DATA_V ;low word + LD Y,A+DATA_V2 + SUB X,X,Y + LD Y,A+V_RES + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + LD X,A+DATA_V ;high word + LD Y,0+MASK_HW + AND X,X,Y + + LD Y,A+DATA_V2 + ST 0+AKKU,A + LD A,0+MASK_HW + + AND Y,Y,A + + LD A,0+AKKU + + SUB X,X,Y + LD Y,A+V_RES + + ST 0+AKKU,A + OR A,0,0 + + VSUB_LOOP_W2: LSR X,X + LSR Y,Y + INC A,A + SUB 0,A,16 + JNZ 0+VSUB_LOOP_W2 + + LD A,0+AKKU + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + INC A,A + SUB 0,A,k + JNZ 0+VSUB_LOOP_W + + ;8 bit + VSUB.B R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VSUB_LOOP_B: OR X,A,0 + ST 0+AKKU,A + LD A,X+DATA_V + ST 0+A_REG,A + LD A,X+DATA_V2 + ST 0+B_REG,A + LD A,X+V_RES + ST 0+RES_REG,A + OR A,0,0 + + VSUB_LOOP_B2: ST 0+I,A + + LD X,0+A_REG + LD Y,0+B_REG + LD A,0+RES_REG + + SUB X,X,Y + AND X,X,$FF + AND A,A,$FF + + SUB 0,X,A + JNZ 0+ERR_VALU + + LD X,0+A_REG + LD Y,0+B_REG + LD A,0+RES_REG + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + LSR X,X + LSR Y,Y + LSR A,A + + ST 0+RES_REG,A + OR A,0,X + ST 0+A_REG,A + OR A,0,Y + ST 0+B_REG,A + + LD A,0+I + INC A,A + SUB 0,A,4 + JNZ 0+VSUB_LOOP_B2 + + LD A,0+AKKU + INC A,A + SUB 0,A,k + JNZ 0+VSUB_LOOP_B + +TEST_VLSL: VLSL.DW R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + ;32 bit + OR A,0,0 + VLSL_LOOP_DW: LD X,A+DATA_V + LSL X,X + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VLSL_LOOP_DW + + ;64 bit + VLSL.QW R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VLSL_LOOP_QW: ST 0+AKKU,A ;reset carry + OR A,0,0 + ST 0+CARRY,A + LD A,0+AKKU + + LD X,A+DATA_V + LSL X,X + + JNC 0+VLSL_QW_NC ; save carry + ST 0+AKKU,A + OR A,0,1 + ST 0+CARRY,A + LD A,0+AKKU + + VLSL_QW_NC: LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + + LD X,A+DATA_V + LD Y,0+CARRY + LSR Y,Y + ROL X,X + + LD Y,A+V_RES + + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + + SUB 0,A,k + JNZ 0+VLSL_LOOP_QW + + ;16bit + VLSL.W R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VLSL_LOOP_W: LD X,A+DATA_V ;low word + LSL X,X + LD Y,A+V_RES + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + LD X,A+DATA_V ;high word + LD Y,0+MASK_HW + AND X,X,Y + + LSL X,X + LD Y,A+V_RES + + ST 0+AKKU,A + OR A,0,0 + + VLSL_LOOP_W2: LSR X,X + LSR Y,Y + INC A,A + SUB 0,A,16 + JNZ 0+VLSL_LOOP_W2 + + LD A,0+AKKU + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + INC A,A + SUB 0,A,k + JNZ 0+VLSL_LOOP_W + + ;8 bit + VLSL.B R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VLSL_LOOP_B: OR X,A,0 + ST 0+AKKU,A + LD A,X+DATA_V + ST 0+A_REG,A + LD A,X+V_RES + ST 0+RES_REG,A + OR A,0,0 + + VLSL_LOOP_B2: ST 0+I,A + + LD X,0+A_REG + + LD A,0+RES_REG + + LSL X,X + AND X,X,$FF + AND A,A,$FF + + SUB 0,X,A + JNZ 0+ERR_VALU + + LD X,0+A_REG + LD A,0+RES_REG + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + ST 0+RES_REG,A + OR A,0,X + ST 0+A_REG,A + + LD A,0+I + INC A,A + SUB 0,A,4 + JNZ 0+VLSL_LOOP_B2 + + LD A,0+AKKU + INC A,A + SUB 0,A,k + JNZ 0+VLSL_LOOP_B + +TEST_VLSR: VLSR.DW R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + ;32 bit + OR A,0,0 + VLSR_LOOP_DW: LD X,A+DATA_V + LSR X,X + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VLSR_LOOP_DW + + ;64 bit + VLSR.QW R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VLSR_LOOP_QW: ST 0+AKKU,A ;reset carry + OR A,0,0 + ST 0+CARRY,A + LD A,0+AKKU + + INC A,A + LD X,A+DATA_V + LSR X,X + + JNC 0+VLSR_QW_NC ; save carry + ST 0+AKKU,A + OR A,0,1 + ST 0+CARRY,A + LD A,0+AKKU + + VLSR_QW_NC: LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + DEC A,A + + LD X,A+DATA_V + LD Y,0+CARRY + LSR Y,Y + ROR X,X + + LD Y,A+V_RES + + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + INC A,A + + SUB 0,A,k + JNZ 0+VLSR_LOOP_QW + + ;16bit + VLSR.W R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VLSR_LOOP_W: LD X,A+DATA_V ;low word + AND X,X,$FFFF + LSR X,X + LD Y,A+V_RES + AND Y,Y,$FFFF + + SUB 0,X,Y + JNZ 0+ERR_VALU + + LD X,A+DATA_V ;high word + LD Y,0+MASK_HW + AND X,X,Y + + LSR X,X + LD Y,A+V_RES + + ST 0+AKKU,A + OR A,0,0 + + VLSR_LOOP_W2: LSR X,X + LSR Y,Y + INC A,A + SUB 0,A,16 + JNZ 0+VLSR_LOOP_W2 + + LD A,0+AKKU + AND X,X,$FFFF + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + INC A,A + SUB 0,A,k + JNZ 0+VLSR_LOOP_W + + ;8 bit + VLSR.B R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VLSR_LOOP_B: OR X,A,0 + ST 0+AKKU,A + LD A,X+DATA_V + ST 0+A_REG,A + LD A,X+V_RES + ST 0+RES_REG,A + OR A,0,0 + + VLSR_LOOP_B2: ST 0+I,A + + LD X,0+A_REG + LD A,0+RES_REG + + AND X,X,$FF + LSR X,X + AND A,A,$FF + + SUB 0,X,A + JNZ 0+ERR_VALU + + LD X,0+A_REG + LD A,0+RES_REG + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + LSR X,X + LSR A,A + + ST 0+RES_REG,A + OR A,0,X + ST 0+A_REG,A + + LD A,0+I + INC A,A + SUB 0,A,4 + JNZ 0+VLSR_LOOP_B2 + + LD A,0+AKKU + INC A,A + SUB 0,A,k + JNZ 0+VLSR_LOOP_B + + + ;vector and scalar commands simultaneous +TEST_SIMUL: OR A,0,DATA_V + VLD R0,0+A + OR A,0,DATA_V2 + VLD R1,0+A + + LD X,0+DATA_A + LD Y,0+DATA_B + OR A,0,0 + VADD.DW R2,R0,R1 + VADD.DW R3,R0,R1 | ADD A,X,Y + VSUB.DW R3,R3,R2 + + OR Y,0,V_RES + VST 0+Y,R3 + + LD X,0+ADD_RES + SUB 0,X,A + JNZ 0+ERR_SIMUL + + OR A,0,0 + SIMUL_LOOP1: LD X,A+V_RES + JNZ 0+ERR_SIMUL + INC A,A + SUB 0,A,k + JNZ 0+SIMUL_LOOP1 + + LD X,0+DATA_A + LD Y,0+DATA_B + OR A,0,0 + VXOR.DW R2,R0,R1 + VXOR.DW R3,R0,R1 | SUB A,X,Y + VSUB.DW R3,R3,R2 + + OR Y,0,V_RES + VST 0+Y,R3 + + LD X,0+SUB_RES + SUB 0,X,A + JNZ 0+ERR_SIMUL + + OR A,0,0 + SIMUL_LOOP2: LD X,A+V_RES + JNZ 0+ERR_SIMUL + INC A,A + SUB 0,A,k + JNZ 0+SIMUL_LOOP2 + + + LD X,0+DATA_A + LD Y,0+DATA_B + OR A,0,0 + VMOV R2,R0 + VMOV R3,R0 | AND A,X,Y + VSUB.DW R3,R3,R2 + + OR Y,0,V_RES + VST 0+Y,R3 + + LD X,0+AND_RES + SUB 0,X,A + JNZ 0+ERR_SIMUL + + OR A,0,0 + SIMUL_LOOP3: LD X,A+V_RES + JNZ 0+ERR_SIMUL + INC A,A + SUB 0,A,k + JNZ 0+SIMUL_LOOP3 + +TEST_VSHUF: OR A,0,use_shuffle + JZ 0+NO_SHUFFLE + OR A,0,DATA_V + VLD R0,0+A + OR A,0,DATA_V2 + VLD R1,0+A + + TEST_VSHUF1: VSHUF R2,R0,R1,00101000011011 ;vwidth + ssss + vn + OR A,0,V_RES + VST 0+A,R2 + + LD X,A+0 + LD A,0+RES_VSHUF_8L + SUB 0,A,X + JNZ 0+ERR_VSHUF + + OR A,0,V_RES + LD Y,A+1 + LD A,0+RES_VSHUF_8H + SUB 0,A,Y + JNZ 0+ERR_VSHUF + + TEST_VSHUF2: VSHUF R2,R0,R1,01110010110001 ;vwidth + ssss + vn + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + LD X,A+V_RES + OR A,0,1 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,1 + LD X,A+V_RES + OR A,0,0 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,2 + LD X,A+V_RES + OR A,0,4 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,3 + LD X,A+V_RES + OR A,0,3 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + TEST_VSHUF3: VSHUF R2,R0,R1,10001101110010 ;vwidth + ssss + vn + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + LD X,A+V_RES + OR A,0,5 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,1 + LD X,A+V_RES + OR A,0,6 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,2 + LD X,A+V_RES + OR A,0,1 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,3 + LD X,A+V_RES + OR A,0,2 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,4 + LD X,A+V_RES + OR A,0,6 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,5 + LD X,A+V_RES + OR A,0,7 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,6 + LD X,A+V_RES + OR A,0,2 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,7 + LD X,A+V_RES + OR A,0,3 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + TEST_VSHUF4: VSHUF R2,R0,R1,11010100100111 ;vwidth + ssss + vn + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + LD X,A+V_RES + OR A,0,13 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,1 + LD X,A+V_RES + OR A,0,14 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,2 + LD X,A+V_RES + OR A,0,15 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,3 + LD X,A+V_RES + OR A,0,16 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + ;-------------- + + OR A,0,4 + LD X,A+V_RES + OR A,0,4 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,5 + LD X,A+V_RES + OR A,0,5 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,6 + LD X,A+V_RES + OR A,0,6 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,7 + LD X,A+V_RES + OR A,0,7 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + ;-------------- + + OR A,0,8 + LD X,A+V_RES + OR A,0,9 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,9 + LD X,A+V_RES + OR A,0,10 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,10 + LD X,A+V_RES + OR A,0,11 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,11 + LD X,A+V_RES + OR A,0,12 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + ;-------------- + + OR A,0,12 + LD X,A+V_RES + OR A,0,0 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,13 + LD X,A+V_RES + OR A,0,1 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,14 + LD X,A+V_RES + OR A,0,2 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + OR A,0,15 + LD X,A+V_RES + OR A,0,3 + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VSHUF + + NO_SHUFFLE: NOP + +TEST_VMUL: OR A,0,use_mul + JZ 0+NO_VMUL + + ;16 bit + VMUL.W R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VMUL_LOOP_W: LD X,A+DATA_V + LD Y,A+DATA_V2 + MUL X,X,Y + LD Y,A+V_RES + SUB 0,X,Y + JNZ 0+ERR_VALU + INC A,A + SUB 0,A,k + JNZ 0+VMUL_LOOP_W + + ;8 bit + VMUL.B R2,R0,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VMUL_LOOP_B: LD X,A+DATA_V ;high word + LD Y,A+DATA_V2 + AND X,X,$FF + AND Y,Y,$FF + MUL X,X,Y + LD Y,A+V_RES + AND Y,Y,$FFFF + SUB 0,X,Y + JNZ 0+ERR_VALU + + LD X,A+DATA_V ;low word + LD Y,A+DATA_V2 + + ST 0+AKKU,A + OR A,0,0 + VMUL_LOOP_B2: LSR X,X + LSR Y,Y + INC A,A + SUB 0,A,16 + JNZ 0+VMUL_LOOP_B2 + AND X,X,$FF + AND Y,Y,$FF + MUL X,X,Y + + LD A,0+AKKU + LD Y,A+V_RES + + OR A,0,0 + VMUL_LOOP_B3: LSR Y,Y + INC A,A + SUB 0,A,16 + JNZ 0+VMUL_LOOP_B3 + + SUB 0,X,Y + JNZ 0+ERR_VALU + + LD A,0+AKKU + INC A,A + SUB 0,A,k + JNZ 0+VMUL_LOOP_B + NO_VMUL: NOP + +TEST_VMOLR: OR A,0,use_mul + JZ 0+NO_VMOLR + + OR A,0,DATA_V + VLD R0,0+A + OR A,0,DATA_V2 + VLD R1,0+A + + VMOL R2,R0 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VMOL_LOOP: LD X,A+V_RES + LD Y,A+DATA_V2 + SUB 0,X,Y + JNZ 0+ERR_VMOLR + SUB 0,A,k + JNZ 0+VMOL_LOOP + + VMOR R2,R1 + OR A,0,V_RES + VST 0+A,R2 + + OR A,0,0 + VMOR_LOOP: LD X,A+V_RES + LD Y,A+DATA_V + SUB 0,X,Y + JNZ 0+ERR_VMOLR + SUB 0,A,k + JNZ 0+VMOR_LOOP + + NO_VMOLR: NOP + +FINISH: JMP 0+FINISH + +ERR_SCALAR: HALT +ERR_COOP: HALT +ERR_VECTOR: HALT +ERR_VALU: HALT +ERR_SIMUL: HALT +ERR_VSHUF: HALT +ERR_VMOLR: HALT + +AKKU: DC 0 +CARRY: DC 0 +X_REG: DC 0 +Y_REG: DC 0 +I: DC 0 + +A_REG: DC 0 +B_REG: DC 0 +RES_REG: DC 0 + Index: tags/arelease/assembler/clvpasm.py =================================================================== --- tags/arelease/assembler/clvpasm.py (nonexistent) +++ tags/arelease/assembler/clvpasm.py (revision 10) @@ -0,0 +1,807 @@ +from pyparsing import * + +#------------------------------------------------------------------------------------------------------ +# CLASS ASSEMBLER +#------------------------------------------------------------------------------------------------------ +class Assembler(object): + def __init__(self, args): + + formaterList = FormaterList() + formaterList.registerComponent("bin", Binary_Formater) + formaterList.registerComponent("vhdl", VHDL_Formater) + formaterList.registerComponent("coe", COE_Formater) + formaterList.registerComponent("symboltable", SYMBOLTABLE_Formater) + + if len(args) != 4: + print + print "usage: python clvpasm.py " + print " supported formats are: " + formaterList.getList() + sys.exit(1) + + format = args[1] + fileNameIn = args[2] + fileNameOut = args[3] + + formater = formaterList.getFormater(format) + + if formater == None: + print + print "error: unsupported format, use one of the following: " + formaterList.getList() + sys.exit(1) + + try: + fileIn = open (fileNameIn,"r") + programcode, symbols = Parser().parse(fileIn.readlines()) + fileIn.close() + except IOError: + print + print "error: unable to open input file: " + fileNameIn + sys.exit(1) + + try: + formaterList.getFormater(format).write(programcode, symbols, fileNameOut) + print "done" + except IOError: + print + print "error: unable to write output file: " + fileNameOut + sys.exit(1) + +#------------------------------------------------------------------------------------------------------ +# CLASS FORMATERLIST +#------------------------------------------------------------------------------------------------------ +class FormaterList(object): + def __init__(self): + self.components = [] + + def getFormater(self, format): + for a in self.components: + if format.lower().lstrip().startswith(a[0].lower()): + return a[1]() + + return None; + + def getList(self): + cmdlist = [] + for a in self.components: + cmdlist.append(a[0]) + + return str(cmdlist) + + def registerComponent(self,format,component): + self.components.append([format,component]) + +#------------------------------------------------------------------------------------------------------ +# CLASS VHDL_FORMATER +#------------------------------------------------------------------------------------------------------ +class VHDL_Formater(object): + def write(self, code, symbols, filename): + + #get last adress + list = sorted(code.iteritems()) + list.reverse() + end = list[0][0] + + f=open(filename,"w") + + f.write("-- ********************************************\n") + f.write("-- * SRAM FILE GENERATED BY HiCoVec ASSEMBLER *\n") + f.write("-- * do not make modifications here *\n") + f.write("-- ********************************************\n\n") + f.write("library ieee;\nuse ieee.std_logic_1164.all;\nuse ieee.std_logic_unsigned.all;\n") + f.write("entity sram is\n\tport (\n\t\tclk : in std_logic;\n\t\twe : in std_logic;\n\t\ten : in std_logic;\n") + f.write("\t\taddr : in std_logic_vector(31 downto 0);\n\t\tdi : in std_logic_vector(31 downto 0);\n") + f.write("\t\tdo : out std_logic_vector(31 downto 0)\n\t);\nend sram;\n") + f.write("architecture rtl of sram is\n") + f.write("\ttype memory_type is array(0 to " + str(end+1) + ") of std_logic_vector(31 downto 0);\n") + f.write("\tsignal memory : memory_type := (\n") + + for i in range(0,end+1): + if code.has_key(i): + f.write('\t\t"' + code[i][0] + '", -- ' + hex(i) + ' : ' +code[i][1] +'\n') + else: + f.write('\t\t"00000000000000000000000000000000", -- ' + hex(i)+'\n') + + f.write('\t\t"00000000000000000000000000000000"'+'\n') + f.write('\t);'+'\n') + + f.write("begin\n\tprocess (clk)\n\tbegin\n\t\tif clk'event and clk = '1' then\n\t\t\tif en = '1' then\n") + f.write("\t\t\t\tif we = '1' then\n\t\t\t\t\tmemory(conv_integer(addr)) <= di;\n\t\t\t\t\tdo <= di;\n") + f.write("\t\t\t\telse\n\t\t\t\t\tdo <= memory(conv_integer(addr));\n\t\t\t\tend if;\n\t\t\tend if;\n\t\tend if;\n") + f.write("\tend process;\nend;\n") + + f.close() + + +#------------------------------------------------------------------------------------------------------ +# CLASS BINARY_FORMATER +#------------------------------------------------------------------------------------------------------ +class Binary_Formater(object): + def write(self, code, symbols, filename): + + #get last adress + list = sorted(code.iteritems()) + list.reverse() + end = list[0][0] + + f=open(filename,"wb") + + for i in range(0,end+1): + if code.has_key(i): + value = string.atoi(code[i][0],2) + m = string.atoi("11111111000000000000000000000000",2) + for j in range(4): + a = (value & m) >> 8 * (3-j) + m = m >> 8 + f.write(chr(a)) + else: + f.write(chr(0) + chr(0) + chr(0) + chr(0)) + f.close() + +#------------------------------------------------------------------------------------------------------ +# CLASS COE_FORMATER +#------------------------------------------------------------------------------------------------------ +class COE_Formater(object): + def write(self, code, symbols, filename): + + #get last adress + list = sorted(code.iteritems()) + list.reverse() + end = list[0][0] + + f=open(filename,"w") + f.write("; COE FILE FOR XILINX CORE GENERATOR\n") + f.write("; depth=" + str(end + 1) + ", and width=32\n") + f.write(";\n") + f.write("memory_initialization_radix=2;\n") + f.write("memory_initialization_vector=\n") + + for i in range(0,end+1): + if code.has_key(i): + f.write(code[i][0] + ",\n") + else: + f.write("00000000000000000000000000000000,\n") + + f.write("00000000000000000000000000000000;\n") + + f.close() + +#------------------------------------------------------------------------------------------------------ +# CLASS SYMBOLTABLE_FORMATER +#------------------------------------------------------------------------------------------------------ +class SYMBOLTABLE_Formater(object): + def write(self, code, symbols, filename): + + f=open(filename,"w") + + for sym, addr in sorted(symbols.iteritems()): + f.write(str(addr) + ":" + str(sym) + "\n") + + f.close() + + +#------------------------------------------------------------------------------------------------------ +# CLASS INSTRUCTION +#------------------------------------------------------------------------------------------------------ +class Instruction(object): + def __init__(self): + self.bincode = [] + for i in range(32): + self.bincode.append("0") + + def revert(self,value): + result = "" + for i in range(len(value),0,-1): + result = result + value[i-1] + return result + + def insert(self, start, end, value): + for i in range (start+1, end, -1): + self.bincode[i-1] = self.revert(value)[i-1-end] + + def tostring(self): + result = "" + for i in range(32,0, -1): + result = result + self.bincode[i-1] + return result + + def tobinary(self,n): + b = "" + if n == 0: + b= "0" + else: + while n > 0: + b = str(n % 2) + b + n = n >> 1 + return b + + def insertImmediate(self, n): + self.insert(15,0,self.tobinary(n).rjust(16,"0")) + + def insertConstant(self, n): + self.insert(31,0,self.tobinary(n).rjust(32,"0")) + + def insertR(self,r): + self.insert(11,8,self.tobinary(r).rjust(4,"0")) + + def insertV(self,v): + self.insert(7,4,self.tobinary(v).rjust(4,"0")) + + def insertW(self,w): + self.insert(3,0,self.tobinary(w).rjust(4,"0")) + + def insertVectorImmediate(self,n): + self.insert(27,20,self.tobinary(n).rjust(8,"0")) + +#------------------------------------------------------------------------------------------------------ +# CLASS PARSER +#------------------------------------------------------------------------------------------------------ +class Parser: + def tointeger(self,s): + if s[0] == "$": + return string.atoi(s[1:], base = 16) + + if s[0] == "%": + return string.atoi(s[1:], base = 2) + + if s[0] == "R": + return string.atoi(s[1:]) + + return string.atoi(s) + + def parse(self, program): + + #create parsed commandlist + errorcounter = 0 + commands = [] + linenr = 0 + + for line in program: + linenr = linenr + 1 + line = line.strip().upper() + + try: + result = LineParser().parseLine(line) + if result.dcommand or result.vcommand or result.command or result.ccommand: + commands.append((result, linenr)) + + except ParseException, err: + print + print "conflict in line " + str(linenr) + ":" + print line + print " "*err.loc + "^ " + "parse error" + errorcounter = errorcounter + 1 + + #create symbol table, assign adresses, detect conflicts + symbols = {} + program = {} + + address = 0 + + for cmd, linenr in commands: + if cmd.dcommand == "ORG": + address = self.tointeger(cmd.address) + + if cmd.dcommand == "EQU": + if symbols.has_key(cmd.symbol): + print + print "conflict in line " + str(linenr) + ":" + print "=> symbol " + cmd.symbol + " has already been defined" + errorcounter = errorcounter + 1 + else: + symbols[cmd.symbol] = self.tointeger(cmd.value) + + if cmd.label: + if symbols.has_key(cmd.label[0]): + print + print "conflict in line " + str(linenr) + ":" + print "=> symbol " + cmd.label[0] + " has already been defined" + errorcounter = errorcounter + 1 + else: + symbols[cmd.label[0]] = address + + if cmd.dcommand != "ORG" and cmd.dcommand != "EQU": + if program.has_key(address): + print + print "conflict in line " + str(linenr) + ":" + print "=> memory address " + hex(address) + " is already in use" + errorcounter = errorcounter + 1 + + program [address] = (cmd, linenr) + address = address + 1 + + + #translate into machine program + code = {} + + for addr, prg in sorted(program.iteritems()): + cmd = prg[0] + linenr = prg[1] + + if cmd.command and cmd.vcommand and cmd.immediate: + print + print "conflict in line " + str(linenr) + ":" + print "=> you can't combine " + cmd.command + " (with immediate value) and " + cmd.vcommand + errorcounter = errorcounter + 1 + + immediate = 0 + + if cmd.immediate: + try: + if cmd.value: + immediate = self.tointeger(cmd.value) + else: + immediate = symbols[cmd.symbol] + except KeyError: + print + print "conflict in line " + str(linenr) + ":" + print "=> symbol " + cmd.symbol + " not declared" + errorcounter = errorcounter + 1 + + if immediate > 65535: + print + print "conflict in line " + str(linenr) + ":" + print "=> immediate value " + cmd.immediate +" (" + hex(immediate) + ") is out of range (max = 0xFFFF)" + errorcounter = errorcounter + 1 + + if cmd.rvector_register: + if self.tointeger(cmd.rvector_register) > Settings().getN()-1: + print + print "conflict in line " + str(linenr) + ":" + print "=> vector register (" + cmd.rvector_register + ") is out of range (R0..R"+ str(Settings().getN()-1) + ")" + errorcounter = errorcounter + 1 + + if cmd.vvector_register: + if self.tointeger(cmd.vvector_register) > Settings().getN()-1: + print + print "conflict in line " + str(linenr) + ":" + print "=> vector register (" + cmd.vvector_register + ") is out of range (R0..R"+ str(Settings().getN()-1) + ")" + errorcounter = errorcounter + 1 + + if cmd.wvector_register: + if self.tointeger(cmd.wvector_register) > Settings().getN()-1: + print + print "conflict in line " + str(linenr) + ":" + print "=> vector register (" + cmd.wvector_register + ") is out of range (R0..R"+ str(Settings().getN()-1) + ")" + errorcounter = errorcounter + 1 + + + i = Instruction() + register = {"0":"00","A":"01","X":"10","Y":"11"} + wordlength = {"B":"00","W":"01","DW":"10","QW":"11"} + + alucommand = False + jumpcommand = False + valucommand = False + immediate_possible = True + + #directive commands + if cmd.dcommand == "DC": + i.insertConstant(self.tointeger(cmd.address)) + + #scalar commands + if cmd.command == "ADD": + alucommand = True + i.insert(29,26,"0000") + + if cmd.command == "ADC": + alucommand = True + i.insert(29,26,"0001") + + if cmd.command == "SUB": + alucommand = True + i.insert(29,26,"0010") + + if cmd.command == "SBC": + alucommand = True + i.insert(29,26,"0011") + + if cmd.command == "AND": + alucommand = True + i.insert(29,26,"1000") + + if cmd.command == "OR": + alucommand = True + i.insert(29,26,"1001") + + if cmd.command == "XOR": + alucommand = True + i.insert(29,26,"1010") + + if cmd.command == "MUL": + alucommand = True + i.insert(29,26,"1011") + + if cmd.command == "INC": + alucommand = True + i.insert(29,26,"0100") + + if cmd.command == "DEC": + alucommand = True + i.insert(29,26,"0110") + + if cmd.command == "LSL": + alucommand = True + i.insert(29,26,"1100") + + if cmd.command == "LSR": + alucommand = True + i.insert(29,26,"1110") + + if cmd.command == "ROL": + alucommand = True + i.insert(29,26,"1101") + + if cmd.command == "ROR": + alucommand = True + i.insert(29,26,"1111") + + if cmd.command == "LD": + i.insert(31,28,"1000") + i.insert(25,24,register[cmd.dregister]) + i.insert(23,22,register[cmd.sregister]) + immediate_possible = True + + if cmd.command == "ST": + i.insert(31,28,"1010") + i.insert(23,22,register[cmd.sregister]) + immediate_possible = True + + if cmd.command == "HALT": + i.insert(31,27,"00101") + + if cmd.command == "NOP": + i.insert(31,29,"000") + + if cmd.command == "JMP": + i.insert(31,24,"00100000") + jumpcommand = True + + if cmd.command == "JAL": + i.insert(31,26,"001000") + i.insert(25,24,register[cmd.dregister]) + jumpcommand = True + + if cmd.command == "JNC": + i.insert(31,24,"00110000") + jumpcommand = True + + if cmd.command == "JC": + i.insert(31,24,"00110100") + jumpcommand = True + + if cmd.command == "JNZ": + i.insert(31,24,"00111000") + jumpcommand = True + + if cmd.command == "JZ": + i.insert(31,24,"00111100") + jumpcommand = True + + if cmd.command == "CLC": + i.insert(31,26,"110000") + i.insert(23,20,"0100") + + if cmd.command == "CLZ": + i.insert(31,26,"110000") + i.insert(23,20,"1000") + + if cmd.command == "SEC": + i.insert(31,26,"110000") + i.insert(23,20,"0101") + + if cmd.command == "SEZ": + i.insert(31,26,"110000") + i.insert(23,20,"1010") + + #common parts of scalar commands + if alucommand == True: + i.insert(31,30,"01"); + i.insert(25,24,register[cmd.dregister]) + i.insert(23,22,register[cmd.sregister]) + immediate_possible = True + + if jumpcommand == True: + i.insert(23,22,register[cmd.sregister]) + immediate_possible = True + + if immediate_possible == True: + if(cmd.immediate): + i.insert(21,20,"00") + i.insert(19,17,"000") + i.insertImmediate(immediate) + else: + if cmd.tregister: + i.insert(21,20,register[cmd.tregister]) + + #vector commands + if cmd.vcommand == "VADD": + i.insert(15,12,"0000") + valucommand = True + + if cmd.vcommand == "VSUB": + i.insert(15,12,"0010") + valucommand = True + + if cmd.vcommand == "VAND": + i.insert(15,12,"1000") + valucommand = True + + if cmd.vcommand == "VOR": + i.insert(15,12,"1001") + valucommand = True + + if cmd.vcommand == "VMUL": + i.insert(15,12,"1011") + valucommand = True + + if cmd.vcommand == "VXOR": + i.insert(15,12,"1010") + valucommand = True + + if cmd.vcommand == "VLSL": + i.insert(15,12,"1100") + valucommand = True + + if cmd.vcommand == "VLSR": + i.insert(15,12,"1110") + valucommand = True + + if cmd.vcommand == "VNOP": + i.insert(19,17,"000") + + if cmd.vcommand == "VMOL": + i.insert(19,17,"001") + i.insert(15,12,"1000") + i.insertR(self.tointeger(cmd.rvector_register)) + i.insertV(self.tointeger(cmd.vvector_register)) + + if cmd.vcommand == "VMOR": + i.insert(19,17,"001") + i.insert(15,12,"1100") + i.insertR(self.tointeger(cmd.rvector_register)) + i.insertV(self.tointeger(cmd.vvector_register)) + + if cmd.vcommand == "VMOV": + i.insert(19,17,"001") + + if cmd.rvector_register and cmd.vvector_register: #vmov r,v + i.insert(15,12,"0001") + i.insertR(self.tointeger(cmd.rvector_register)) + i.insertV(self.tointeger(cmd.vvector_register)) + + if cmd.immediate: + if immediate > 255: + print + print "conflict in line " + str(linenr) + ":" + print "=> immediate value " + cmd.immediate +" (" + hex(immediate) + ") is out of range (max = 0xFF)" + errorcounter = errorcounter + 1 + else: + if cmd.rvector_register: #vmov r, r + i.insertVectorImmediate(immediate) + i.insert(15,12,"0010") + i.insertR(self.tointeger(cmd.rvector_register)) + + if cmd.vvector_register: #vmov r,r + i.insertVectorImmediate(immediate) + i.insert(15,12,"0011") + i.insertV(self.tointeger(cmd.vvector_register)) + + #common parts of vector commands + if valucommand == True: + i.insert(19,18,"01") + i.insert(17,16,wordlength[cmd.width]) + i.insertR(self.tointeger(cmd.rvector_register)) + i.insertV(self.tointeger(cmd.vvector_register)) + + if cmd.wvector_register: + i.insertW(self.tointeger(cmd.wvector_register)) + + #cooperative commands + if cmd.ccommand == "VLD": + i.insert(31,28,"1001") + i.insert(23,22,register[cmd.sregister]) + i.insert(21,20,register[cmd.tregister]) + i.insert(19,18,"10") + i.insert(15,12,"0010") + i.insertR(self.tointeger(cmd.rvector_register)) + + if cmd.ccommand == "VST": + i.insert(31,26,"101100") + i.insert(23,22,register[cmd.sregister]) + i.insert(21,20,register[cmd.tregister]) + i.insert(19,18,"10") + i.insert(15,12,"0011") + i.insertV(self.tointeger(cmd.vvector_register)) + + if cmd.ccommand == "MOV": + if cmd.rvector_register and cmd.tregister and cmd.sregister: #mov r(t),s + i.insert(31,26,"101110") + i.insert(23,22,register[cmd.sregister]) + i.insert(21,20,register[cmd.tregister]) + i.insert(19,18,"10") + i.insert(15,12,"0100") + i.insertR(self.tointeger(cmd.rvector_register)) + + if cmd.vvector_register and cmd.tregister and cmd.dregister: #mov d,v(t) + i.insert(31,26,"101111") + i.insert(25,24,register[cmd.dregister]) + i.insert(21,20,register[cmd.tregister]) + i.insert(19,18,"10") + i.insert(15,12,"0101") + i.insertV(self.tointeger(cmd.vvector_register)) + + if cmd.ccommand == "MOVA": + i.insert(31,26,"101101") + i.insert(23,22,register[cmd.sregister]) + i.insert(19,18,"10") + i.insert(15,12,"0110") + i.insertR(self.tointeger(cmd.rvector_register)) + + if cmd.ccommand == "VSHUF": + i.insert(31,29,"000") + i.insert(19,18,"11") + i.insert(17,16,cmd.perm[0:2]) + i.insert(15,12,cmd.perm[2:6]) + i.insert(27,20,cmd.perm[6:14]) + i.insertR(self.tointeger(cmd.rvector_register)) + i.insertV(self.tointeger(cmd.vvector_register)) + i.insertW(self.tointeger(cmd.wvector_register)) + + code [addr] = (i.tostring(), string.join(cmd)) + + if errorcounter > 0: + print + print str(errorcounter) + " error(s) found => output has not been written" + sys.exit(1) + else: + return code, symbols + +#------------------------------------------------------------------------------------------------------ +# CLASS LINEPARSER +#------------------------------------------------------------------------------------------------------ +class LineParser: + def parseLine(self,line): + + expression = Forward() + + dec_value = Word("0123456789", min=1) + hex_value = Word("$","ABCDEF0123456789", min=2) + bin_value = Word("%","10", min=2) + + value = (dec_value ^ hex_value ^ bin_value).setResultsName("value") + ident = Word( alphas, alphanums + "_" ).setResultsName("symbol") + + immediate = (value ^ ident).setResultsName("immediate") + perm = Word("10", min=14, max=14).setResultsName("perm") + + length = (Literal("B") ^ Literal("W") ^ Literal("DW") ^ Literal("QW")).setResultsName("width") + mult_length = (Literal("B") ^ Literal("W")).setResultsName("width") + + width = ("." + length) + mult_width = ("." + mult_length) + + label = (ident + ":").setResultsName("label") + + comment = ( ";" + restOfLine).setResultsName("comment") + + dregister = (Literal("A") ^ Literal("X") ^ Literal("Y") ^ Literal("0")).setResultsName("dregister") + sregister = (Literal("A") ^ Literal("X") ^ Literal("Y") ^ Literal("0")).setResultsName("sregister") + tregister = (Literal("A") ^ Literal("X") ^ Literal("Y")).setResultsName("tregister") + akku = Literal("A") + + rvector_register = Word("R","0123456789",min=2).setResultsName("rvector_register") + vvector_register = Word("R","0123456789",min=2).setResultsName("vvector_register") + wvector_register = Word("R","0123456789",min=2).setResultsName("wvector_register") + + + directive_cmd_keyword_1 = (Keyword("ORG") ^ Keyword("DC")).setResultsName("dcommand") + directive_cmd_keyword_2 = (Keyword("EQU")).setResultsName("dcommand") + + directive_cmd_1 = directive_cmd_keyword_1 + value.setResultsName("address") + directive_cmd_2 = directive_cmd_keyword_2 + ident + value + + directive_cmd = (directive_cmd_1 ^ directive_cmd_2) + + alu_cmd_keyword_1 = (Keyword("INC") ^ Keyword("DEC") ^ Keyword("LSL") ^ Keyword("LSR") ^ Keyword("ROL") \ + ^ Keyword("ROR")).setResultsName("command") + + alu_cmd_keyword_2 = (Keyword("ADD") ^ Keyword("ADC") ^ Keyword("SUB") ^ Keyword("SBC") ^ Keyword("AND") \ + ^ Keyword("OR") ^ Keyword("XOR") ^ Keyword("MUL")).setResultsName("command") + + + alu_cmd_1 = alu_cmd_keyword_1 + dregister + "," + sregister + alu_cmd_2 = alu_cmd_keyword_2 + dregister + "," + sregister + "," + (tregister ^ immediate) + alu_cmd = (alu_cmd_1 ^ alu_cmd_2) + + jmp_cmd_keyword_1 = (Keyword("JMP") ^ Keyword("JNC") ^ Keyword("JC") ^ Keyword("JNZ") ^ Keyword("JZ")) \ + .setResultsName("command") + jmp_cmd_keyword_2 = Keyword("JAL").setResultsName("command") + + jmp_cmd_1 = jmp_cmd_keyword_1 + Optional("[") + sregister + "+" + (tregister ^ immediate) + Optional("]") + jmp_cmd_2 = jmp_cmd_keyword_2 + dregister + "," + Optional("[") + sregister + "+" + (tregister ^ immediate) + Optional("]") + jmp_cmd = (jmp_cmd_1 ^ jmp_cmd_2) + + inherent_cmd_keyword = (Keyword ("HALT") ^ Keyword ("NOP") ^ Keyword ("CLC") ^ Keyword ("CLZ") ^ Keyword ("SEC") \ + ^ Keyword ("SEZ")).setResultsName("command") + + inherent_cmd = inherent_cmd_keyword + + load_cmd_keyword = Keyword("LD").setResultsName("command") + load_cmd = load_cmd_keyword + dregister + "," + Optional("[") + sregister + "+" + (tregister ^ immediate) + Optional("]") + + store_cmd_keyword = Keyword("ST").setResultsName("command") + store_cmd = store_cmd_keyword + Optional("[") + sregister + "+" + (tregister ^ immediate) + Optional("]") +"," + akku + + scalar_command = (alu_cmd ^ jmp_cmd ^ inherent_cmd ^ load_cmd ^ store_cmd) + + mov_cmd_keyword = Keyword("MOV").setResultsName("ccommand") + mov_cmd_1 = mov_cmd_keyword + rvector_register + "(" + tregister + ")" + "," + sregister + mov_cmd_2 = mov_cmd_keyword + dregister + "," + vvector_register + "(" + tregister + ")" + mov_cmd = (mov_cmd_1 ^ mov_cmd_2) + + vld_cmd_keyword = Keyword("VLD").setResultsName("ccommand") + vld_cmd = vld_cmd_keyword + rvector_register + "," + Optional("[") + sregister + "+" + tregister + Optional("]") + + vst_cmd_keyword = Keyword("VST").setResultsName("ccommand") + vst_cmd = vst_cmd_keyword + Optional("[") + sregister + "+" + tregister + Optional("]") + "," + vvector_register + + shuffle_cmd_keyword = Keyword("VSHUF").setResultsName("ccommand") + shuffle_cmd = shuffle_cmd_keyword + rvector_register + "," + vvector_register + "," + wvector_register + "," + perm + + mova_cmd_keyword = Keyword("MOVA").setResultsName("ccommand") + mova_cmd = mova_cmd_keyword + rvector_register + "," + sregister + + coop_command = (mov_cmd ^ vld_cmd ^ vst_cmd ^ shuffle_cmd ^ mova_cmd) + + valu_cmd_keyword_1 = (Keyword("VADD") ^ Keyword("VSUB") ^ Keyword("VAND") ^ Keyword("VOR") ^ Keyword("VXOR")) \ + .setResultsName("vcommand") + + valu_cmd_keyword_2 = (Keyword("VLSL") ^ Keyword("VLSR")).setResultsName("vcommand") + + valu_cmd_keyword_3 = Keyword("VMUL").setResultsName("vcommand") + + valu_cmd_1 = valu_cmd_keyword_1 + width + rvector_register + "," + vvector_register + "," + wvector_register + valu_cmd_2 = valu_cmd_keyword_2 + width + rvector_register + "," + vvector_register + valu_cmd_3 = valu_cmd_keyword_3 + mult_width + rvector_register + "," + vvector_register + "," + wvector_register + valu_cmd = (valu_cmd_1 ^ valu_cmd_2 ^ valu_cmd_3) + + vnop_cmd_keyword = Keyword("VNOP").setResultsName("vcommand") + vnop_cmd = vnop_cmd_keyword + + vmov_cmd_keyword = Keyword("VMOV").setResultsName("vcommand") + vmov_cmd_1 = vmov_cmd_keyword + rvector_register + "," + vvector_register + vmov_cmd_2 = vmov_cmd_keyword + rvector_register + "," + "R" + "<" + immediate + ">" + vmov_cmd_3 = vmov_cmd_keyword + "R" + "<" + immediate + ">" + "," + vvector_register + vmov_cmd = (vmov_cmd_1 ^ vmov_cmd_2 ^ vmov_cmd_3) + + vmolr_cmd_keyword = (Keyword("VMOL") ^ Keyword("VMOR")).setResultsName("vcommand") + vmolr_cmd = vmolr_cmd_keyword + rvector_register + "," + vvector_register + + vector_command = (valu_cmd ^ vnop_cmd ^ vmov_cmd ^ vmolr_cmd) + + command = ((directive_cmd ^ scalar_command ^ coop_command ^ vector_command) \ + ^ (scalar_command + "|" + vector_command )\ + ^ (vector_command + "|" + scalar_command )) + + + expression << (Optional((Optional(label) + command)) + Optional(comment) + lineEnd) + result = expression.parseString(line) + return result + +#------------------------------------------------------------------------------------------------------ +# CLASS SETTINGS +#------------------------------------------------------------------------------------------------------ +class Settings(object): + def getN(self): + return 16 + + def getK(self): + return 16 + +#------------------------------------------------------------------------------------------------------ +# MAIN PROGRAM +#------------------------------------------------------------------------------------------------------ +if __name__ == '__main__': + Assembler(sys.argv) + + Index: tags/arelease/assembler/pyparsing.py =================================================================== --- tags/arelease/assembler/pyparsing.py (nonexistent) +++ tags/arelease/assembler/pyparsing.py (revision 10) @@ -0,0 +1,2942 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2006 Paul T. McGuire +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +#from __future__ import generators + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form ", !"):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word( alphas ) + "," + Word( alphas ) + "!" + + hello = "Hello, World!" + print hello, "->", greet.parseString( hello ) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The parsed results returned from parseString() can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments +""" +__version__ = "1.4.4-Mod-HaraldManske" +__versionTime__ = "19 October 2006 23:11" +__author__ = "Paul McGuire " + + +#Modified by Harald Manske: +# - removed Deprication Warning of Upcase class +# - created Downcase class + +import string +import copy,sys +import warnings +import re +import sre_constants +import xml.sax.saxutils +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError, e: + # The Python docs (http://docs.python.org/ref/customization.html#l2h-182) + # state that "The return value must be a string object". However, does a + # unicode object (being a subclass of basestring) count as a "string + # object"? + # If so, then return a unicode object: + return unicode(obj) + # Else encode it... but how? There are many choices... :) + # Replace unprintables with escape codes? + #return unicode(obj).encode(sys.getdefaultencoding(), 'backslashreplace_errors') + # Replace unprintables with question marks? + #return unicode(obj).encode(sys.getdefaultencoding(), 'replace') + # ... + +def _str2dict(strg): + return dict( [(c,0) for c in strg] ) + #~ return set( [c for c in strg] ) + +class _Constants(object): + pass + +alphas = string.lowercase + string.uppercase +nums = string.digits +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + __slots__ = ( "loc","msg","pstr","parserElement" ) + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc, msg, elem=None ): + self.loc = loc + self.msg = msg + self.pstr = pstr + self.parserElement = elem + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError, aname + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join( [line_str[:line_column], markerString, line_str[line_column:]]) + return line_str.strip() + +class ParseException(ParseBaseException): + """exception thrown when parse expressions don't match class""" + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ReparseException(ParseBaseException): + def __init_( self, newstring, restartLoc ): + self.newParseText = newstring + self.reparseLoc = restartLoc + + +class RecursiveGrammarException(Exception): + """exception thrown by validate() if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class ParseResults(object): + """Structured parse results, to provide multiple means of access to the parsed data: + - as a list (len(results)) + - by list index (results[0], results[1], etc.) + - by attribute (results.) + """ + __slots__ = ( "__toklist", "__tokdict", "__doinit", "__name", "__parent", "__accumNames" ) + def __new__(cls, toklist, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist, name=None, asList=True, modal=True ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + if isinstance(toklist, list): + self.__toklist = toklist[:] + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + # this line is related to debugging the asXML bug + #~ asList = False + + if name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not toklist in (None,'',[]): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = (toklist.copy(),-1) + else: + self[name] = (ParseResults(toklist[0]),-1) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v ): + if isinstance(v,tuple): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,int): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = self + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + del self.__toklist[i] + else: + del self._tokdict[i] + + def __contains__( self, k ): + return self.__tokdict.has_key(k) + + def __len__( self ): return len( self.__toklist ) + def __nonzero__( self ): return len( self.__toklist ) > 0 + def __iter__( self ): return iter( self.__toklist ) + def keys( self ): + """Returns all named result keys.""" + return self.__tokdict.keys() + + def items( self ): + """Returns all named result keys and values as a list of tuples.""" + return [(k,self[k]) for k in self.__tokdict.keys()] + + def values( self ): + """Returns all named result values.""" + return [ v[-1][0] for v in self.__tokdict.values() ] + + def __getattr__( self, name ): + if name not in self.__slots__: + if self.__tokdict.has_key( name ): + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + return None + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = ( lambda a: (a<0 and offset) or (a+offset) ) + otheritems = other.__tokdict.items() + otherdictitems = [(k,(v[0],addoffset(v[1])) ) for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = self + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + del other + return self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + out = "[" + sep = "" + for i in self.__toklist: + if isinstance(i, ParseResults): + out += sep + _ustr(i) + else: + out += sep + repr(i) + sep = ", " + out += "]" + return out + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """Returns the parse results as a nested list of matching tokens, all converted to strings.""" + out = [] + for res in self.__toklist: + if isinstance(res,ParseResults): + out.append( res.asList() ) + else: + out.append( res ) + return out + + def asDict( self ): + """Returns the named parse results as dictionary.""" + return dict( self.items() ) + + def copy( self ): + """Returns a new copy of a ParseResults object.""" + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.""" + nl = "\n" + out = [] + namedItems = dict( [ (v[1],k) for (k,vlist) in self.__tokdict.items() for v in vlist ] ) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + worklist = self.__toklist + for i,res in enumerate(worklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], namedItemsOnly and doctag is None, nextLevelIndent,formatted)] + else: + out += [ res.asXML(None, namedItemsOnly and doctag is None, nextLevelIndent,formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = xml.sax.saxutils.escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", xmlBodyText, "" ] + + out += [ nl, indent, "" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + """Returns the results name for this token expression.""" + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + self.__tokdict.values()[0][0][1] in (0,-1)): + return self.__tokdict.keys()[0] + else: + return None + + def dump(self,indent='',depth=0): + """Diagnostic method for listing out the contents of a ParseResults. + Accepts an optional indent argument so that this string can be embedded + in a nested display of other data.""" + out = [] + out.append( indent+str(self.asList()) ) + keys = self.items() + keys.sort() + for k,v in keys: + if out: + out.append('\n') + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v.keys(): + #~ out.append('\n') + out.append( v.dump(indent,depth+1) ) + #~ out.append('\n') + else: + out.append(str(v)) + else: + out.append(str(v)) + #~ out.append('\n') + return "".join(out) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + """ + return (loc 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print "Match",expr,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print "Matched",expr,"->",toks.asList() + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print "Exception raised:", exc + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + + def setDefaultWhitespaceChars( chars ): + """Overrides the default whitespace chars + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + setDefaultWhitespaceChars = staticmethod(setDefaultWhitespaceChars) + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True + self.errmsg = "" + self.modalResults = True + self.debugActions = ( None, None, None ) + self.re = None + + def copy( self ): + """Make a copy of this ParserElement. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element.""" + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """Define name for this expression, for use in debugging.""" + self.name = name + self.errmsg = "Expected " + self.name + return self + + def setResultsName( self, name, listAllMatches=False ): + """Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original ParserElement object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + """ + newself = self.copy() + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def normalizeParseActionArgs( f ): + """Internal method used to decorate parse actions that take fewer than 3 arguments, + so that all parse actions can be called as f(s,l,t).""" + STAR_ARGS = 4 + + try: + restore = None + if isinstance(f,type): + restore = f + f = f.__init__ + if f.func_code.co_flags & STAR_ARGS: + return f + numargs = f.func_code.co_argcount + if hasattr(f,"im_self"): + numargs -= 1 + if restore: + f = restore + except AttributeError: + try: + # not a function, must be a callable object, get info from the + # im_func binding of its bound __call__ method + if f.__call__.im_func.func_code.co_flags & STAR_ARGS: + return f + numargs = f.__call__.im_func.func_code.co_argcount + if hasattr(f.__call__,"im_self"): + numargs -= 1 + except AttributeError: + # not a bound method, get info directly from __call__ method + if f.__call__.func_code.co_flags & STAR_ARGS: + return f + numargs = f.__call__.func_code.co_argcount + if hasattr(f.__call__,"im_self"): + numargs -= 1 + + #~ print "adding function %s with %d args" % (f.func_name,numargs) + if numargs == 3: + return f + else: + if numargs == 2: + def tmp(s,l,t): + return f(l,t) + elif numargs == 1: + def tmp(s,l,t): + return f(t) + else: #~ numargs == 0: + def tmp(s,l,t): + return f() + return tmp + normalizeParseActionArgs = staticmethod(normalizeParseActionArgs) + + def setParseAction( self, *fns ): + """Define action to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as fn(s,loc,toks), + fn(loc,toks), fn(toks), or just fn(), where: + - s = the original string being parsed + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a ParseResults object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value.""" + self.parseAction = map(self.normalizeParseActionArgs, list(fns)) + return self + + def addParseAction( self, *fns ): + """Add parse action to expression's list of parse actions. See setParseAction_.""" + self.parseAction += map(self.normalizeParseActionArgs, list(fns)) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + fn(s,loc,expr,err) where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw ParseFatalException + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self.skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print "Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = loc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + #~ except ReparseException, retryEx: + #~ pass + except ParseException, err: + #~ print "Exception raised:", err + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = loc + if self.mayIndexError or loc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and doActions: + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseException, err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + + if debugging: + #~ print "Matched",self,"->",retTokens.asList() + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + return self._parse( instring, loc, doActions=False )[0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + if doActions and self.parseAction: + return self._parseNoCache( instring, loc, doActions, callPreParse ) + lookup = (self,instring,loc,callPreParse) + if lookup in ParserElement._exprArgCache: + value = ParserElement._exprArgCache[ lookup ] + if isinstance(value,Exception): + if isinstance(value,ParseBaseException): + value.loc = loc + raise value + return value + else: + try: + ParserElement._exprArgCache[ lookup ] = \ + value = self._parseNoCache( instring, loc, doActions, callPreParse ) + return value + except ParseBaseException, pe: + ParserElement._exprArgCache[ lookup ] = pe + raise + + _parse = _parseNoCache + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + _exprArgCache = {} + def resetCache(): + ParserElement._exprArgCache.clear() + resetCache = staticmethod(resetCache) + + _packratEnabled = False + def enablePackrat(): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method ParserElement.enablePackrat(). If + your program uses psyco to "compile as you go", you must call + enablePackrat before calling psyco.full(). If you do not do this, + Python will crash. For best results, call enablePackrat() immediately + after importing pyparsing. + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + ParserElement._parse = ParserElement._parseCache + enablePackrat = staticmethod(enablePackrat) + + def parseString( self, instring ): + """Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if self.keepTabs: + loc, tokens = self._parse( instring, 0 ) + else: + loc, tokens = self._parse( instring.expandtabs(), 0 ) + return tokens + + def scanString( self, instring, maxMatches=sys.maxint ): + """Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + maxMatches argument, to clip scanning after 'n' matches are found.""" + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = instring.expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + matches += 1 + yield tokens, preloc, nextLoc + loc = nextLoc + + def transformString( self, instring ): + """Extension to scanString, to modify matching text with modified tokens that may + be returned from a parse action. To use transformString, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking transformString() on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. transformString() returns the resulting transformed string.""" + out = [] + lastE = 0 + # force preservation of s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + return "".join(out) + + def searchString( self, instring, maxMatches=sys.maxint ): + """Another extension to scanString, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + maxMatches argument, to clip searching after 'n' matches are found. + """ + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + + def __add__(self, other ): + """Implementation of + operator - returns And""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return And( [ self, other ] ) + + def __radd__(self, other ): + """Implementation of += operator""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return other + self + + def __or__(self, other ): + """Implementation of | operator - returns MatchFirst""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """Implementation of |= operator""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return other | self + + def __xor__(self, other ): + """Implementation of ^ operator - returns Or""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """Implementation of ^= operator""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return other ^ self + + def __and__(self, other ): + """Implementation of & operator - returns Each""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return Each( [ self, other ] ) + + def __rand__(self, other ): + """Implementation of right-& operator""" + if isinstance( other, basestring ): + other = Literal( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot add element of type %s to ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return other & self + + def __invert__( self ): + """Implementation of ~ operator - returns NotAny""" + return NotAny( self ) + + def suppress( self ): + """Suppresses the output of this ParserElement; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """Disables the skipping of whitespace before matching the characters in the + ParserElement's defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """Overrides default behavior to expand s to spaces before parsing the input string. + Must be called before parseString when the input grammar contains elements that + match characters.""" + self.keepTabs = True + return self + + def ignore( self, other ): + """Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + """ + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append( other ) + else: + self.ignoreExprs.append( Suppress( other ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """Enable display of debugging messages while doing pattern matching.""" + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """Enable display of debugging messages while doing pattern matching.""" + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """Check defined expressions for valid structure, check for infinite recursive definitions.""" + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename ): + """Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + f = open(file_or_filename, "rb") + file_contents = f.read() + f.close() + return self.parseString(file_contents) + + +class Token(ParserElement): + """Abstract ParserElement subclass, for defining atomic matching patterns.""" + def __init__( self ): + super(Token,self).__init__( savelist=False ) + self.myException = ParseException("",0,"",self) + + def setName(self, name): + s = super(Token,self).setName(name) + self.errmsg = "Expected " + self.name + s.myException.msg = self.errmsg + return s + + +class Empty(Token): + """An empty token, will always match.""" + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """A token that will never match.""" + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + self.myException.msg = self.errmsg + + def parseImpl( self, instring, loc, doActions=True ): + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + +class Literal(Token): + """Token to exactly match a specified string.""" + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.myException.msg = self.errmsg + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class Keyword(Token): + """Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with Literal:: + Literal("if") will match the leading 'if' in 'ifAndOnlyIf'. + Keyword("if") will not; it will only match the leading 'if in 'if x=1', or 'if(y==2)' + Accepts two optional constructor arguments in addition to the keyword string: + identChars is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$"; caseless allows case-insensitive + matching, default is False. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=DEFAULT_KEYWORD_CHARS, caseless=False ): + super(Keyword,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.myException.msg = self.errmsg + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = _str2dict(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + setDefaultKeywordChars = staticmethod(setDefaultKeywordChars) + + +class CaselessLiteral(Literal): + """Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + self.myException.msg = self.errmsg + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class CaselessKeyword(Keyword): + def __init__( self, matchString, identChars=Keyword.DEFAULT_KEYWORD_CHARS ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class Word(Token): + """Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0 ): + super(Word,self).__init__() + self.initCharsOrig = initChars + self.initChars = _str2dict(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = _str2dict(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = _str2dict(initChars) + + self.maxSpecified = max > 0 + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = sys.maxint + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.myException.msg = self.errmsg + self.mayIndexError = False + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.bodyCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + try: + self.re = re.compile( self.reString ) + except: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + loc = result.end() + return loc,result.group() + + if not(instring[ loc ] in self.initChars): + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + + if throwException: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(Word,self).__str__() + except: + pass + + + if self.strRepr is None: + + def charsAsStr(s): + if len(s)>4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + """Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + """ + def __init__( self, pattern, flags=0): + """The parameters pattern and flags are passed to the re.compile() function as-is. See the Python re module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if len(pattern) == 0: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error,e: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.myException.msg = self.errmsg + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d.keys(): + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + """Token for matching strings that are delimited by quoting characters. + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None): + """ + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=None) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=None) + - multiline - boolean indicating whether quotes can span multiple lines (default=False) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=True) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=None => same as quoteChar) + """ + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if len(quoteChar) == 0: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if len(endQuoteChar) == 0: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join(["%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)]) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error,e: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.myException.msg = self.errmsg + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + loc = result.end() + ret = result.group() + print ret + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern,"\g<1>",ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """Token for matching words composed of characters *not* in a given set. + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = sys.maxint + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.myException.msg = self.errmsg + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is " \\t\\n". Also takes optional min, max, and exact arguments, + as defined for the Word class.""" + whiteStrs = { + " " : "", + "\t": "", + "\n": "", + "\r": "", + "\f": "", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join([c for c in self.whiteChars if c not in self.matchWhite]) ) + #~ self.leaveWhitespace() + self.name = ("".join([White.whiteStrs[c] for c in self.matchWhite])) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + self.myException.msg = self.errmsg + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = sys.maxint + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + #~ raise ParseException( instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + + return loc, instring[start:loc] + + +class PositionToken(Token): + def __init__( self ): + super(PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(PositionToken): + """Token to advance to a specific column of input text; useful for tabular report scraping.""" + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self.skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + +class LineStart(PositionToken): + """Matches if current position is at the beginning of a line within the parse string""" + def __init__( self ): + super(LineStart,self).__init__() + self.setWhitespaceChars( " \t" ) + self.errmsg = "Expected start of line" + self.myException.msg = self.errmsg + + def preParse( self, instring, loc ): + preloc = super(LineStart,self).preParse(instring,loc) + if instring[preloc] == "\n": + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + if not( loc==0 or ( loc maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError, err: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + if loc2 > maxMatchLoc: + maxMatchLoc = loc2 + maxMatchExp = e + + if maxMatchLoc < 0: + if self.exprs: + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + return maxMatchExp._parse( instring, loc, doActions ) + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = Literal( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join( [ _ustr(e) for e in self.exprs ] ) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """Requires that at least one ParseExpression is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the '|' operator. + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if exprs: + self.mayReturnEmpty = False + for e in self.exprs: + if e.mayReturnEmpty: + self.mayReturnEmpty = True + break + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException, err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError, err: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if self.exprs: + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = Literal( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join( [ _ustr(e) for e in self.exprs ] ) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + +class Each(ParseExpression): + """Requires all given ParseExpressions to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the '&' operator. + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = True + for e in self.exprs: + if not e.mayReturnEmpty: + self.mayReturnEmpty = False + break + self.skipWhitespace = True + self.optionals = [ e.expr for e in exprs if isinstance(e,Optional) ] + self.multioptionals = [ e.expr for e in exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + + def parseImpl( self, instring, loc, doActions=True ): + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(e) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join( [ _ustr(e) for e in tmpReqd ] ) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = ParseResults([]) + for r in resultlist: + dups = {} + for k in r.keys(): + if k in finalResults.keys(): + tmp = ParseResults(finalResults[k]) + tmp += ParseResults(r[k]) + dups[k] = tmp + finalResults += ParseResults(r) + for k,v in dups.items(): + finalResults[k] = v + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join( [ _ustr(e) for e in self.exprs ] ) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """Abstract subclass of ParserElement, for combining and post-processing parsed tokens.""" + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + expr = Literal(expr) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """Lookahead matching of the given parse expression. FollowedBy + does *not* advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. FollowedBy always returns a null token list.""" + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """Lookahead to disallow matching with the given parse expression. NotAny + does *not* advance the parsing position within the input string, it only + verifies that the specified parse expression does *not* match at the current + position. Also, NotAny does *not* skip over leading whitespace. NotAny + always returns a null token list. May be constructed using the '~' operator.""" + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + self.myException = ParseException("",0,self.errmsg,self) + + def parseImpl( self, instring, loc, doActions=True ): + try: + self.expr.tryParse( instring, loc ) + except (ParseException,IndexError): + pass + else: + #~ raise ParseException(instring, loc, self.errmsg ) + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + + +class ZeroOrMore(ParseElementEnhance): + """Optional repetition of zero or more of the given expression.""" + def __init__( self, expr ): + super(ZeroOrMore,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + tokens = [] + try: + loc, tokens = self.expr._parse( instring, loc, doActions ) + hasIgnoreExprs = ( len(self.ignoreExprs) > 0 ) + while 1: + if hasIgnoreExprs: + preloc = self.skipIgnorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self.expr._parse( instring, preloc, doActions ) + if tmptokens or tmptokens.keys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + + def setResultsName( self, name, listAllMatches=False ): + ret = super(ZeroOrMore,self).setResultsName(name,listAllMatches) + ret.saveAsList = True + return ret + + +class OneOrMore(ParseElementEnhance): + """Repetition of one or more of the given expression.""" + def parseImpl( self, instring, loc, doActions=True ): + # must be at least one + loc, tokens = self.expr._parse( instring, loc, doActions ) + try: + hasIgnoreExprs = ( len(self.ignoreExprs) > 0 ) + while 1: + if hasIgnoreExprs: + preloc = self.skipIgnorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self.expr._parse( instring, preloc, doActions ) + if tmptokens or tmptokens.keys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + + def setResultsName( self, name, listAllMatches=False ): + ret = super(OneOrMore,self).setResultsName(name,listAllMatches) + ret.saveAsList = True + return ret + +class _NullToken(object): + def __bool__(self): + return False + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """Optional matching of the given expression. + A default return string can also be specified, if the optional expression + is not found. + """ + def __init__( self, exprs, default=_optionalNotMatched ): + super(Optional,self).__init__( exprs, savelist=False ) + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + + +class SkipTo(ParseElementEnhance): + """Token for skipping over all undefined text until the matched expression is found. + If include is set to true, the matched expression is also consumed. The ignore + argument is used to define grammars (typically quoted strings and comments) that + might contain false matches. + """ + def __init__( self, other, include=False, ignore=None ): + super( SkipTo, self ).__init__( other ) + if ignore is not None: + self.expr = self.expr.copy() + self.expr.ignore(ignore) + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + self.errmsg = "No match found for "+_ustr(self.expr) + self.myException = ParseException("",0,self.errmsg,self) + + def parseImpl( self, instring, loc, doActions=True ): + startLoc = loc + instrlen = len(instring) + expr = self.expr + while loc <= instrlen: + try: + loc = expr.skipIgnorables( instring, loc ) + expr._parse( instring, loc, doActions=False, callPreParse=False ) + if self.includeMatch: + skipText = instring[startLoc:loc] + loc,mat = expr._parse(instring,loc) + if mat: + return loc, [ skipText, mat ] + else: + return loc, [ skipText ] + else: + return loc, [ instring[startLoc:loc] ] + except (ParseException,IndexError): + loc += 1 + exc = self.myException + exc.loc = loc + exc.pstr = instring + raise exc + +class Forward(ParseElementEnhance): + """Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the Forward variable using the '<<' operator. + + Note: take care when assigning to Forward not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the Forward:: + fwdExpr << (a | b | c) + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = Literal(other) + self.expr = other + self.mayReturnEmpty = other.mayReturnEmpty + self.strRepr = None + return self + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = Forward + return "Forward: "+retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret << self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """Abstract subclass of ParseExpression, for converting parsed results.""" + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + + +class Upcase(TokenConverter): + """Converter to upper case all matching tokens.""" + def __init__(self, *args): + super(Upcase,self).__init__(*args) + + def postParse( self, instring, loc, tokenlist ): + return map( string.upper, tokenlist ) + + +class Downcase(TokenConverter): + """Converter to upper case all matching tokens.""" + def __init__(self, *args): + super(Downcase,self).__init__(*args) + + def postParse( self, instring, loc, tokenlist ): + return map( string.lower, tokenlist ) + + + +class Combine(TokenConverter): + """Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying 'adjacent=False' in the constructor. + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and len(retToks.keys())>0: + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """Converter to return the matched tokens as a list - useful for returning tokens of ZeroOrMore and OneOrMore expressions.""" + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + """ + def __init__( self, exprs ): + super(Dict,self).__init__( exprs ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = ("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = (tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.keys()): + tokenlist[ikey] = (dictvalue,i) + else: + tokenlist[ikey] = (dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """Converter for ignoring the results of a parsed expression.""" + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """Wrapper for parse actions, to ensure they are only called once.""" + def __init__(self, methodCall): + self.callable = ParserElement.normalizeParseActionArgs(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(): + self.called = False + +def traceParseAction(f): + """Decorator for debugging parse actions.""" + f = ParserElement.normalizeParseActionArgs(f) + def z(*paArgs): + thisFunc = f.func_name + s,l,t = paArgs[-3:] + if len(paArgs)>3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %s)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception, exc: + sys.stderr.write( "<", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join( [ _escapeRegexRangeChars(sym) for sym in symbols] ) ) + else: + return Regex( "|".join( [ re.escape(sym) for sym in symbols] ) ) + except: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst( [ parseElementClass(sym) for sym in symbols ] ) + +def dictOf( key, value ): + """Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the Dict, ZeroOrMore, and Group tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the Dict results can include named token + fields. + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +_bslash = "\\" +printables = "".join( [ c for c in string.printable if c not in string.whitespace ] ) + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_printables_less_backslash = "".join([ c for c in printables if c not in r"\]" ]) +_escapedHexChar = Combine( Suppress(_bslash + "0x") + Word(hexnums) ).setParseAction(lambda s,l,t:unichr(int(t[0],16))) +_escapedOctChar = Combine( Suppress(_bslash) + Word("0","01234567") ).setParseAction(lambda s,l,t:unichr(int(t[0],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(_printables_less_backslash,exact=1) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = "[" + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +_expanded = lambda p: (isinstance(p,ParseResults) and ''.join([ unichr(c) for c in range(ord(p[0]),ord(p[1])+1) ]) or p) + +def srange(s): + r"""Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be:: + a single character + an escaped character with a leading backslash (such as \- or \]) + an escaped hex character with a leading '\0x' (\0x21, which is a '!' character) + an escaped octal character with a leading '\0' (\041, which is a '!' character) + a range of any of the above, separated by a dash ('a-z', etc.) + any combination of the above ('aeiouy', 'a-zA-Z0-9_$', etc.) + """ + try: + return "".join([_expanded(part) for part in _reBracketExpr.parseString(s).body]) + except: + return "" + +def replaceWith(replStr): + """Helper method for common parse actions that simply return a literal value. Especially + useful when used with transformString(). + """ + def _replFunc(*args): + return [replStr] + return _replFunc + +def removeQuotes(s,l,t): + """Helper parse action for removing quotation marks from parsed quoted strings. + To use, add this parse action to quoted string using:: + quotedString.setParseAction( removeQuotes ) + """ + return t[0][1:-1] + +def upcaseTokens(s,l,t): + """Helper parse action to convert tokens to upper case.""" + return [ str(tt).upper() for tt in t ] + +def downcaseTokens(s,l,t): + """Helper parse action to convert tokens to lower case.""" + return [ str(tt).lower() for tt in t ] + +def keepOriginalText(s,startLoc,t): + import inspect + """Helper parse action to preserve original parsed text, + overriding any nested parse actions.""" + f = inspect.stack()[1][0] + try: + endloc = f.f_locals["loc"] + finally: + del f + return s[startLoc:endloc] + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + tagAttrName = Word(alphanums) + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + Keyword(tagStr) + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join( [ c for c in printables if c not in ">" ] ) + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + Keyword(tagStr,caseless=True) + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine("") + + openTag = openTag.setResultsName("start"+"".join(tagStr.replace(":"," ").title().split())).setName("<%s>" % tagStr) + closeTag = closeTag.setResultsName("end"+"".join(tagStr.replace(":"," ").title().split())).setName("" % tagStr) + + return openTag, closeTag + +def makeHTMLTags(tagStr): + """Helper to construct opening and closing tag expressions for HTML, given a tag name""" + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """Helper to construct opening and closing tag expressions for XML, given a tag name""" + return _makeTags( tagStr, True ) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def operatorPrecedence( baseExpr, opList ): + """Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal + - numTerms is the number of terms for this operator (must + be 1 or 2) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants opAssoc.RIGHT and opAssoc.LEFT. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted) + """ + ret = Forward() + lastExpr = baseExpr | ( Suppress('(') + ret + Suppress(')') ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + thisExpr = Forward().setName("expr%d" % i) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = Group( lastExpr + opExpr ) + elif arity == 2: + matchExpr = Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + raise ValueError, "operator must be unary (1) or binary (2)" + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + matchExpr = Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + raise ValueError, "operator must be unary (1) or binary (2)" + else: + raise ValueError, "operator must indicate right or left associativity" + if pa: + matchExpr.setParseAction( pa ) + thisExpr << ( matchExpr | lastExpr ) + lastExpr = thisExpr + ret << lastExpr + return ret + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xfe]") + +dblQuotedString = Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\.))*"').setName("string enclosed in double quotes") +sglQuotedString = Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\.))*'").setName("string enclosed in single quotes") +quotedString = Regex(r'''(?:"(?:[^"\n\r\\]|(?:"")|(?:\\.))*")|(?:'(?:[^'\n\r\\]|(?:'')|(?:\\.))*')''').setName("quotedString using single or double quotes") + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Regex(r"/\*(?:[^*]*\*+)+?/").setName("C style comment") + +htmlComment = Regex(r"") +restOfLine = Regex(r".*").leaveWhitespace() +dblSlashComment = Regex(r"\/\/(\\\n|.)*").setName("// comment") +cppStyleComment = Regex(r"/(?:\*(?:[^*]*\*+)+?/|/[^\n]*(?:\n[^\n]*)*?(?:(?", + try: + tokens = simpleSQL.parseString( teststring ) + tokenlist = tokens.asList() + print tokenlist + print "tokens = ", tokens + print "tokens.columns =", tokens.columns + print "tokens.tables =", tokens.tables + print tokens.asXML("SQL",True) + except ParseException, err: + print err.line + print " "*(err.column-1) + "^" + print err + print + + selectToken = CaselessLiteral( "select" ) + fromToken = CaselessLiteral( "from" ) + + ident = Word( alphas, alphanums + "_$" ) + columnName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens ) + columnNameList = Group( delimitedList( columnName ) )#.setName("columns") + tableName = delimitedList( ident, ".", combine=True ).setParseAction( upcaseTokens ) + tableNameList = Group( delimitedList( tableName ) )#.setName("tables") + simpleSQL = ( selectToken + \ + ( '*' | columnNameList ).setResultsName( "columns" ) + \ + fromToken + \ + tableNameList.setResultsName( "tables" ) ) + + test( "SELECT * from XYZZY, ABC" ) + test( "select * from SYS.XYZZY" ) + test( "Select A from Sys.dual" ) + test( "Select AA,BB,CC from Sys.dual" ) + test( "Select A, B, C from Sys.dual" ) + test( "Select A, B, C from Sys.dual" ) + test( "Xelect A, B, C from Sys.dual" ) + test( "Select A, B, C frox Sys.dual" ) + test( "Select" ) + test( "Select ^^^ frox Sys.dual" ) + test( "Select A, B, C from Sys.dual, Table2 " )

powered by: WebSVN 2.1.0

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