changeset 178:c694ec551f34

Added lex yacc test scripts
author Windel Bouwman
date Sat, 04 May 2013 12:07:17 +0200
parents 460db5669efa
children 0f3b1adfd416
files python/pylex.py python/pyyacc.py python/stlink.py python/x86.py
diffstat 4 files changed, 340 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/pylex.py	Sat May 04 12:07:17 2013 +0200
@@ -0,0 +1,113 @@
+import collections
+
+""" Simple script to try fsa construction """
+# 0. possible characters:
+chars = ['a', 'b', 'c', 'd']
+# 1. pattern definitions:
+P1 = "aab"
+P2 = "abbad"
+P3 = "caababbac"
+patterns = [P1, P2, P3]
+# 2. input string:
+txt = "ababaabaaabaabaacabbadbababaabbaab"
+
+# Generator functions to generate states and transitions:
+class Item:
+   def __init__(self, regex, dotpos):
+      self.regex = regex
+      self.dotpos = dotpos
+   def __eq__(self, other):
+      if type(self) is type(other):
+         return self.regex == other.regex and self.dotpos == other.dotpos
+      return False
+   def __repr__(self):
+      return '{0} _dot_ {1}'.format(self.regex[0:self.dotpos], self.regex[self.dotpos:])
+   def __hash__(self):
+      return (self.regex, self.dotpos).__hash__()
+   def matches(self, ch):
+      if self.dotpos < len(self.regex):
+         if self.regex[self.dotpos] == ch:
+            return True
+      return False
+   @property
+   def IsReduce(self):
+      return self.dotpos == len(self.regex)
+
+def InitialItemSet():
+   s = set()
+   for p in patterns:
+      s.add(Item(p, 0))
+   return frozenset(s)
+
+def NextItemSet(its, ch):
+   nis = set()
+   for item in its:
+      if item.matches(ch):
+         nis.add(Item(item.regex, item.dotpos + 1))
+   return frozenset(nis)
+
+def ClassOfToken(its):
+   for i in its:
+      if i.IsReduce:
+         return i.regex
+   return None
+
+sw = frozenset() # Empty set
+states = set()
+transitions = {}
+s0 = InitialItemSet()
+
+def preCalc():
+   states.add(s0)
+   worklist = [s0]
+   while len(worklist) > 0:
+      its = worklist.pop(0)
+      for ch in chars:
+         nis = NextItemSet(its, ch)
+         if nis and not nis in states:
+            states.add(nis)
+            worklist.append(nis)
+            transitions[(its, ch)] = nis
+      
+preCalc()
+print(len(states), states)
+print(len(transitions), transitions)
+
+# Lex function:
+Token = collections.namedtuple('Token', 'pos len name')
+
+def getNextToken():
+   readIndex = 0
+   while True:
+      startTok = readIndex
+      endTok = None
+      classTok = None
+      itemSet = s0
+      while itemSet:
+         ch = txt[readIndex]
+         # Lookup next itemset:
+         if (itemSet, ch) in transitions:
+            itemSet = transitions[(itemSet, ch)]
+         else:
+            itemSet = sw
+         # check what we recognized:
+         ct = ClassOfToken(itemSet)
+         if ct:
+            classTok = ct
+            endTok = readIndex
+         readIndex += 1
+      print('restart')
+      if classTok:
+         token = Token(startTok, endTok - startTok, classTok)
+         readIndex = endTok + 1
+      else:
+         readIndex = startTok + 1
+         token = None
+      yield token
+
+for tok in getNextToken():
+   print(tok)
+   if tok:
+      print(txt)
+      print(' ' * tok.pos + tok.name)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/pyyacc.py	Sat May 04 12:07:17 2013 +0200
@@ -0,0 +1,160 @@
+
+class GrammarError(Exception):
+   pass
+
+class Grammar:
+   def __init__(self, terminals):
+      self.terminals = terminals
+      self.nonterminals = []
+      self.productions = []
+      self.states = None
+      self.start_symbol = None
+   def add_production(self, name, symbols):
+      p = Production(name, symbols)
+      self.productions.append(p)
+      if not name in self.nonterminals:
+         self.nonterminals.append(name)
+   def set_start(self, start):
+      self.start_symbol = start
+   def get_start(self):
+      return self.start_symbol
+   StartSymbol = property(get_start, set_start)
+   def productionsForName(self, name):
+      return [p for p in self.productions if p.name == name]
+   @property
+   def Symbols(self):
+      return self.nonterminals + self.terminals
+   def calcFollow(self, name):
+      """ Determines the follow set for a given name """
+      f = set()
+      # TODO
+      return f
+
+   def e_closure(self, S):
+      something_changed = True
+      while something_changed:
+         something_changed = False
+         worklist = list(S)
+         for item in worklist:
+            if item.IsShift and item.Next in self.nonterminals:
+               n = item.Next
+               for add_p in self.productionsForName(n):
+                  i = Item(add_p, 0)
+                  if not i in S:
+                     S.add(i)
+                     something_changed = True
+      return frozenset(S)
+   def calcInitialItemSet(self):
+      nis = set()
+      for p in self.productionsForName(self.StartSymbol):
+         nis.add(Item(p, 0))
+      return self.e_closure(nis)
+   def calcNextItemSet(self, itemset, symbol):
+      nis = set()
+      for item in itemset:
+         if item.IsShift and item.Next == symbol:
+            nis.add(Item(item.production, item.dotpos + 1))
+      return self.e_closure(nis)
+   def calcTables(self):
+      print(self.nonterminals + self.terminals)
+      self.states = set()
+      self.goto_table = {}
+      self.action_table = {}
+      iis = self.calcInitialItemSet()
+      self.s0 = iis
+      print(len(iis), iis)
+      worklist = [iis]
+      self.states.add(iis)
+      while len(worklist) > 0:
+         itemset = worklist.pop(0)
+         has_goto = False
+         for symbol in self.Symbols:
+            nis = self.calcNextItemSet(itemset, symbol)
+            if nis:
+               self.goto_table[(itemset, symbol)] = nis
+               has_goto = True
+               if not nis in self.states:
+                  worklist.append(nis)
+                  self.states.add(nis)
+         if has_goto:
+            self.action_table[itemset] = 'shift', 's'
+            for item in itemset:
+               assert item.IsShift, item
+         else:
+            # Check for reduce-reduce conflicts:
+            assert len(itemset) == 1
+            item = list(itemset)[0]
+            assert item.IsReduce
+            self.action_table[itemset] = 'reduce', item.production
+      print(self.Symbols)
+      print(len(nis), nis, self.states)
+      for s, i in zip(self.states, range(len(self.states))):
+         print(i, s)
+         
+   def parse(self, toks):
+      stack = [self.s0]
+      while stack[-1] != 'input':
+         action, p = self.action_table[stack[-1]]
+         print(action, p)
+         if action == 'shift':
+            stack.append(toks.pop(0))
+            s, i = stack[-2:]
+            stack.append(self.goto_table[(s, i)])
+         else:
+            for s in p.symbols:
+               stack.pop()
+               stack.pop()
+            stack.append(p.name)
+            s, i = stack[-2:]
+            stack.append(self.goto_table[(s, i)])
+
+class Production:
+   def __init__(self, name, symbols):
+      self.name = name
+      self.symbols = symbols
+   def __repr__(self):
+      return '{0} -> {1}'.format(self.name, self.symbols)
+   
+class Item:
+   def __init__(self, production, dotpos):
+      self.production = production
+      self.dotpos = dotpos
+   def __eq__(self, other):
+      if type(other) is type(self):
+         return (self.production, self.dotpos) == (other.production, other.dotpos)
+      return False
+   def __hash__(self):
+      return (self.production, self.dotpos).__hash__()
+   @property
+   def IsReduce(self):
+      return self.dotpos == len(self.production.symbols)
+   @property
+   def IsShift(self):
+      return not self.IsReduce
+   @property
+   def Next(self):
+      return self.production.symbols[self.dotpos]
+   def matches(self, symbol):
+      return self.Next == symbol
+   def __repr__(self):
+      return '{0} -> {1} _dot_ {2}'.format(self.production.name, ' '.join(self.production.symbols[0:self.dotpos]), ' '.join(self.production.symbols[self.dotpos:]))
+
+# Test it:
+# 1. define a simple grammar:
+g = Grammar(['EOF', 'identifier', '(', ')', '+'])
+g.add_production('input', ['expression', 'EOF'])
+g.add_production('expression', ['term'])
+g.add_production('expression', ['expression', '+', 'term'])
+g.add_production('term', ['identifier'])
+g.add_production('term', ['(', 'expression', ')'])
+g.StartSymbol = 'input'
+
+# 2. define input:
+tokens = ['identifier', '+', 'identifier', 'EOF']
+
+# 3. build tables
+g.calcTables()
+
+# 4. feed input
+g.parse(tokens)
+
--- a/python/stlink.py	Mon Apr 22 23:54:54 2013 +0200
+++ b/python/stlink.py	Sat May 04 12:07:17 2013 +0200
@@ -3,6 +3,13 @@
 from devices import Interface, STLinkException, registerInterface
 import adi
 
+"""
+   More or less copied from:
+     https://github.com/texane/stlink
+   Tracing from:
+     https://github.com/obe1line/stlink-trace
+
+"""
 ST_VID, STLINK2_PID = 0x0483, 0x3748
 
 def checkDevice(device):
@@ -39,6 +46,7 @@
 
 JTAG_WRITEDEBUG_32BIT = 0x35
 JTAG_READDEBUG_32BIT = 0x36
+TRACE_GET_BYTE_COUNT = 0x42
 
 # cortex M3
 CM3_REG_CPUID = 0xE000ED00
@@ -172,19 +180,55 @@
       cmd = bytearray(16)
       cmd[0:2] = DEBUG_COMMAND, DEBUG_FORCEDEBUG
       self.send_recv(cmd, 2)
+   
+   # Tracing:
+   def traceEnable(self):
+      self.write_debug32(0xE000EDF0, 0xA05F0003)
 
-   def traceEnable(self):
+      # Enable TRCENA:
       DEMCR = 0xE000EDFC
       v = self.read_debug32(DEMCR)
       v |= (1 << 24)
       self.write_debug32(DEMCR, v)
 
+      # ?? Enable write??
+      self.write_debug32(0xE0002000, 0x2) #
+
+      # DBGMCU_CR:
+      self.write_debug32(0xE0042004, 0x27) # Enable trace in async mode
+
+      # TPIU config:
+      self.write_debug32(0xE0040004, 0x00000001) # current port size register --> 1 == port size = 1
+      self.write_debug32(0xE0040010, 0x23) # random clock divider??
+      self.write_debug32(0xE00400F0, 0x2) # selected pin protocol (2 == NRZ)
+      self.write_debug32(0xE0040304, 0x100) # continuous formatting
+      
+      # ITM config:
+      self.write_debug32(0xE0000FB0, 0xC5ACCE55) # Unlock write access to ITM
+      self.write_debug32(0xE0000F80, 0x00010005) # ITM Enable, sync enable, ATB=1
+      self.write_debug32(0xE0000E00, 0xFFFFFFFF) # Enable all trace ports in ITM
+      self.write_debug32(0xE0000E40, 0x0000000F) # Set privilege mask for all 32 ports.
+   def writePort0(self, v32):
+      self.write_debug32(0xE0000000, v32)
+   def getTraceByteCount(self):
+      cmd = bytearray(16)
+      cmd[0:2] = DEBUG_COMMAND, 0x42
+      reply = self.send_recv(cmd, 2)
+      return struct.unpack('<H', reply[0:2])[0]
+   def readTraceData(self):
+      bsize = self.getTraceByteCount()
+      if bsize > 0:
+         td = self.recv_ep3(bsize)
+         print(td)
+      else:
+         print('no trace data')
+
    # Helper 1 functions:
    def write_debug32(self, address, value):
       cmd = bytearray(16)
       cmd[0:2] = DEBUG_COMMAND, JTAG_WRITEDEBUG_32BIT
       cmd[2:10] = struct.pack('<II', address, value)
-      self.send_recv(cmd, 2)
+      r = self.send_recv(cmd, 2)
    def read_debug32(self, address):
       cmd = bytearray(16)
       cmd[0:2] = DEBUG_COMMAND, JTAG_READDEBUG_32BIT
@@ -231,6 +275,8 @@
       self.devHandle.bulkWrite(2, tx) # write to endpoint 2
       if rxsize > 0:
          return self.devHandle.bulkRead(1, rxsize) # read from endpoint 1
+   def recv_ep3(self, rxsize):
+      return self.devHandle.bulkRead(3, rxsize)
 
 if __name__ == '__main__':
    # Test program
@@ -263,6 +309,14 @@
    regs = sl.read_all_regs()
    for i in range(len(regs)):
       print('R{0}=0x{1:X}'.format(i, regs[i]))
+
+   print('tracing')
+   sl.traceEnable()
+   sl.run()
+   sl.writePort0(0x1337) # For test
+   time.sleep(0.1)
+   td = sl.readTraceData()
+   print('trace data:', td)
    
    # Test CoreSight registers:
    idr4 = sl.read_debug32(0xE0041fd0)
--- a/python/x86.py	Mon Apr 22 23:54:54 2013 +0200
+++ b/python/x86.py	Sat May 04 12:07:17 2013 +0200
@@ -58,6 +58,17 @@
       print(dag.mapping)
       bb.dag = dag
 
+# Machine code interface:
+class MachineOperand:
+   """ Single machine operand """
+   pass
+
+class MachineInstruction:
+   def __init__(self, opcode):
+      self.opcode = opcode
+      self.operands = []
+
+
 # x86 specific:
 class AsmLabel:
    def __init__(self, lab):