Mercurial > lcfOS
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):