Hi,
is there a way to get breakpoint-adresses for source code lines directly
from simulavr (with the python interface)?

Currently, I call avr-gdb via subprocess.Popen and evaluate the output
of "break" commands (see attached code, get_breakpoint_adresses). But
that seems a bit clumsy.

Sebastian
import unittest
import pysimulavr
import subprocess
import re

class XPin(pysimulavr.Pin):
  def __init__(self, dev, name, pinname, state = None):
    pysimulavr.Pin.__init__(self)
    self.name = name
    if state is not None: self.SetPin(state)
    # hold the connecting net here, it have not be destroyed, if we leave this method
    self.__net = pysimulavr.Net()
    self.__net.Add(self)
    self.__net.Add(dev.GetPin(pinname))
    
  def SetInState(self, pin):
    pysimulavr.Pin.SetInState(self, pin)
    if pin.toChar() != self.toChar():
        # print "%s='%s'" % (self.name, pin.toChar())
        self.SetPin(pin.toChar())

class SingleDeviceTestCase(unittest.TestCase):
    def setUp(self):
        self.__sc = pysimulavr.SystemClock.Instance()
        self.__sc.ResetClock()
        self.device = pysimulavr.AvrFactory.instance().makeDevice(self.MCU)
        self.device.Load(self.PROGRAM)
        self.device.SetClockFreq(self.CLOCK_SETTING)
        self.__sc.Add(self.device)
        
        self.messages = []
        self.breakpoint_callbacks = {}
    
    def tearDown(self):
        del self.device

    def setPin(self, pin, state):
        self.pins[pin].SetPin(state)
    def getPin(self, pin):
        return self.pins[pin].toChar()
    def showPin(self, pin):
        p = self.pins[pin]
        self.message('%s = %s' % (p.name, p.toChar()))
        
    def getCurrentTime(self):
        return self.__sc.GetCurrentTime() / 1000000.0

    def read_uint8(self, symbol):
        addr = self.device.data.GetAddressAtSymbol(symbol)
        return self.device.getRWMem(addr)
    
    def message(self, m):
        # This could be improved...
        if len(self.messages) == 0:
            print '\n\t' + str(m)
        else:
            print '\t' + str(m)
        self.messages.append(m)

    def add_breakpoint_callback(self, key, callback):
        addr = self.breakpoint_adresses[key]
        self.breakpoint_callbacks.setdefault(addr, []).append((callback, key))
    def generic_breakpoint_callback(self, key):
        self.message('Breakpoint %s reached, time = %s' % (key, self.getCurrentTime()))
        return 0 # Don't stop
    def runSteps(self, steps):
        last_pc = 0 # Needed to avoid double-callbacks for multi-step instructions
        for i in range(steps):
            self.assertEqual(self.__sc.Step(), 0)
            if self.device.PC in self.breakpoint_callbacks and self.device.PC != last_pc:
                for callback, key in self.breakpoint_callbacks[self.device.PC]:
                    if callback(key):
                        return i
            last_pc = self.device.PC

def read_until_prompt(file, prompt='(gdb)'):
    lines = []
    while 1:
        line = file.readline(len(prompt))
        if line == prompt:
            return lines
        line += file.readline()
        lines.append(line)
def ignore_until_prompt(file, prompt='(gdb)'):
    lines = read_until_prompt(file, prompt)
    #~ print '-'*10 + ' ignoring'
    #~ print ''.join(lines)
breakpoint_marker = re.compile(r'/\* *Breakpoint (?P<key>.*)\*/')
breakpoint_adress_output = re.compile(r'Breakpoint \d+ at 0x(?P<bp_addr>[0-9a-fA-F]+):.*')
def get_breakpoint_adresses(debug_directory, program, sourcefiles):
    source_positions = {}
    breakpoint_adresses = {}
    
    # Search for lines with a match for the regex breakpoint_marker.
    # Store filenames and linenumbers in source_positions.
    for filename in sourcefiles:
        for i, line in enumerate(open(debug_directory+filename, 'r')):
            m = breakpoint_marker.search(line)
            if m:
                source_positions[m.group('key').strip()] = '%s:%s' % (filename, i+1)
                
    # Call avr-gdb to get the adresses where avr-gdb sets breakpoints
    # when you set breakpoints at the source lines.
    # In breakpoint_adresses, store these addreses under the the key from the breakpoint_marker.
    p = subprocess.Popen(['avr-gdb'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
    ignore_until_prompt(p.stdout) # start message
    p.stdin.write('file ' + debug_directory + program + '\n')
    ignore_until_prompt(p.stdout) # load message
    for key, source_position in source_positions.items():
        p.stdin.write('break ' + source_position + '\n')
        result = ''.join(read_until_prompt(p.stdout)).strip()
        m = breakpoint_adress_output.match(result)
        if m:
            # The adress is divided by two because flash is adressed in 16 bit words
            # (see datasheet, In-System Reprogrammable Flash Program Memory)
            breakpoint_adresses[key] = int(m.group('bp_addr'), 16)/2
        else:
            print "couldn't match '%s'" % result
    p.stdin.write('quit\n')
    unconsumed = p.stdout.read()
    #~ if unconsumed.strip():
        #~ print '-'*10 + ' ignoring'
        #~ print unconsumed
    return breakpoint_adresses

if __name__ == "__main__":
    pass
_______________________________________________
Simulavr-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/simulavr-devel

Reply via email to