Hi,
I want to use simulavrxx to test my AVR code (the original
AVR studio was way too slow, and possibilities to interface
the simulated core with my programs and Verilog are really
important to me).
My AVR code intensively uses the UART interface.
Unfortunately it also sends smetimes the double quote character
("), which caused the Tcl/Tk GUI to crash.
Additionally I wanted to have more tight integration between my code
and the simulavr, and therefore I have decided to use pysimulavr.

My first finding was, that I'm unable to access periferials
defined in serialtx and serialrx from pysimulavr, but I've worked around this by adding
  #include "ui/ui.h"
  #include "ui/extpin.h"
  #include "ui/keyboard.h"
  #include "ui/lcd.h"
  #include "ui/scope.h"
  #include "ui/serialrx.h"
  #include "ui/serialtx.h"
and
  %include "ui/ui.h"
  %include "ui/extpin.h"
  %include "ui/keyboard.h"
  %include "ui/lcd.h"
  %include "ui/scope.h"
  %include "ui/serialrx.h"
  %include "ui/serialtx.h"
lines to the pysimulavr.i file (I attach the modified version).

After recompilation, I have built my simulation file mytest.py (attached).

i have found, that if I instantiated my UART receiver as below:
class AVRtest(SimulavrAdapter):

  def __init__(self):
    self.dmanSingleDeviceApplication()
    proc, elffile = argv[1].split(":")
    self.device = self.loadDevice(proc, elffile)
    self.device.SetClockFreq(125)

rs_in=pysimulavr.Net()
mytest = AVRtest()
mytest.dmanStart()
d1=mytest.device.GetPin("D1")
rs_in.Add(d1)
rx=pysimulavr.SerialRxBuffered()
rx.SetBaudRate(9600)
r0=rx.GetPin("rx")
rs_in.Add(r0)

the UART receiver was not simulated.
To cure it, I had to modify the SimulavrAdapter class, adding the following method:

def addComponent(self,c):
    self.__sc.Add(c)
    return 0

Then I could register mu UART interface with:
  mytest.addComponent(rx)
right after its creation.

What's interesting, is that when I have done the same with the SerialTxBuffered component, I got the following error after invocation of mytest.doRun:

FATAL: file ui/serialtx.cpp: line 98: Illegal state in SerialTx
It appears, that SerialTxBuffered must register itself in its
void SerialTxBuffered::Send(unsigned char data) procedure:
[...]
      SystemClock::Instance().Add(this);
[...]
to work correctly.

The final version of my test file "mytest.py" is also attached.

My test is put in the examples/python directory and may be run with:
LD_LIBRARY_PATH=../../src/.libs \
PYTHONPATH=../../src \
/usr/bin/python -i mytest.py atmega16:code.elf

I hope, that this code may be useful for someone else, and I'd also
appretiate any improvements and corrections, if I've done something in a wrong way.
--
Regards,
WZab

# -*- coding: UTF-8 -*-
# Python simulation with UART
import sys
import os
import select

from sys import argv

import pysimulavr
from ex_utils import SimulavrAdapter

class AVRtest(SimulavrAdapter):
  
  def __init__(self):
    self.dmanSingleDeviceApplication()
    proc, elffile = argv[1].split(":")
    self.device = self.loadDevice(proc, elffile)
    self.device.SetClockFreq(125)

def uart_rcv():
  while rx.Size()>0:
    os.write(my_tty,chr(rx.Get()))
    #os.flush(my_tty)
def uart_snd(text):
  for c in text: 
    tx.Send(ord(c))

def myrun():
   #This procedure performs the main loop
   #It should be rather done in two separate threads,
   #But this is only a "proof of the concept" implementation
   while True:
     mytest.doStep(10000) #You may need to adjust this value to assure smooth interaction...
     uart_rcv()
     (r,w,x)=select.select([my_tty,],[],[],0)
     if r:
       c=os.read(my_tty,1)
       if c!= "":
         tx.Send(ord(c))
      
if __name__ == "__main__":
  rs_in=pysimulavr.Net()
  rs_out=pysimulavr.Net()
  mytest = AVRtest()
  mytest.dmanStart()
  d1=mytest.device.GetPin("D1")
  d0=mytest.device.GetPin("D0")
  rs_in.Add(d1)
  rs_out.Add(d0)
  #rx=pysimulavr.SerialRxBasic()
  rx=pysimulavr.SerialRxBuffered() 
  mytest.addComponent(rx)
  rx.SetBaudRate(9600)
  r0=rx.GetPin("rx")
  rs_in.Add(r0)
  tx=pysimulavr.SerialTxBuffered() 
  #mytest.addComponent(tx)
  tx.SetBaudRate(9600)
  r1=tx.GetPin("tx")
  rs_out.Add(r1)
  #Create the pseudoterminal
  (my_tty, slave_tty) = os.openpty()
  slave_name = os.ttyname(slave_tty)
  os.spawnl(os.P_NOWAIT,"/usr/bin/xterm","xterm", "-e", "microcom", "-p",slave_name)
  # Enter the main loop  
  myrun()
# EOF
%module(directors="1") pysimulavr

%{

  #include "systemclocktypes.h"
  #include "avrdevice.h"
  #include "systemclock.h"
  #include "hardware.h"
  #include "externaltype.h"
  #include "irqsystem.h"
  #include "pin.h"
  #include "net.h"
  #include "ui/ui.h"
  #include "ui/extpin.h"
  #include "ui/keyboard.h"
  #include "ui/lcd.h"
  #include "ui/scope.h"
  #include "ui/serialrx.h"
  #include "ui/serialtx.h"
  #include "rwmem.h"
  #include "hwsreg.h"
  #include "avrfactory.h"
  #include "memory.h"
  #include "flash.h"
  #include "hweeprom.h"
  #include "breakpoint.h"
  #include "global.h"
  #include "avrerror.h"
  #include "pysimulationmember.h"
  #include "hwport.h"
  #include "hwstack.h"
  
  // to get devices registered (automatically on linux, but necessary on 
windows)
  #include "atmega128.h"
  #include "at4433.h"
  #include "at8515.h"
  #include "atmega668base.h"
  #include "atmega16_32.h"
  #include "attiny2313.h"
  
%}

%include "std_vector.i"
%include "std_iostream.i"
%include "std_sstream.i"

namespace std {
   %template(DWordVector) vector<dword>;
};

%exception {
  try {
    $action
  } catch(char const* s) {
    PyErr_SetString(PyExc_SystemError, s);
    return NULL;
  } catch(int i) {
    PyErr_Format(PyExc_RuntimeError, "%d", i);
    return NULL;
  }
}

%include "types.h"
%include "systemclocktypes.h"
%include "simulationmember.h"

%feature("director") PySimulationMember;
%include "pysimulationmember.h"

%include "externaltype.h"
%include "pinnotify.h"
%include "traceval.h"
%include "irqsystem.h"
%include "avrdevice.h"

%extend DumpManager {
  void addDumpVCD(const std::string &vcdname,
                  const std::string &istr,
                  const std::string &timebase,
                  const bool rstrobe,
                  const bool wstrobe) {
    DumpVCD *d = new DumpVCD(vcdname, timebase, rstrobe, wstrobe);
    $self->addDumper(d, $self->load(istr));
  }
}

%extend AvrDevice {
  // getRWMem and setRWMem are deprecated, don't use it in new code!
  unsigned char getRWMem(unsigned a) { return $self->GetRWMem(a); }
  bool setRWMem(unsigned a, unsigned char v) { return $self->SetRWMem(a, v); }
}

%include "systemclock.h"

%extend SystemClock {
  int Step() {
    bool untilCoreStepFinished = false;
    return $self->Step(untilCoreStepFinished);
  }
}

%feature("director") Hardware;
%include "hardware.h"
%include "hwport.h"
%include "hwstack.h"

%feature("director") Pin;
%include "pin.h"

%extend Pin {
  char toChar() {
    char c = *$self;
    return c;
  }
  void SetPin(const char c) {
    *$self = c;
  }
}

%include "net.h"
%include "ui/ui.h"
%include "ui/extpin.h"
%include "ui/keyboard.h"
%include "ui/lcd.h"
%include "ui/scope.h"
%include "ui/serialrx.h"
%include "ui/serialtx.h"
%feature("director") RWMemoryMember;
%include "rwmem.h"

%include "hwsreg.h"
%extend RWSreg {
  unsigned char GetValue(void) {
    unsigned char v = *$self;
    return v;
  }
  void SetValue(unsigned char v) {
    RWMemoryMember* m = $self;
    *m = v;
  }
}

%include "avrfactory.h"
%include "memory.h"

%extend Memory {
  unsigned char GetMemory(unsigned int a) {
    if(a < $self->GetSize())
      return $self->myMemory[a];
    return 0;
  }
  void PyWriteMem(char *src, unsigned int offset, unsigned int secSize) {
    $self->WriteMem((unsigned char *)src, offset, secSize);
  }
}

%include "flash.h"
%include "hweeprom.h"
%include "breakpoint.h"

%extend Breakpoints {
  void RemoveBreakpoint(unsigned bp) {
    Breakpoints::iterator ii;
    if ((ii = find($self->begin(), $self->end(), bp)) != $self->end()) 
$self->erase(ii);
  }
  void AddBreakpoint(unsigned bp) {
    $self->push_back(bp);
  }
}

%include "global.h"
%include "avrerror.h"

// to get devices registered (automatically on linux, but necessary on windows)
%include "atmega128.h"
%include "at4433.h"
%include "at8515.h"
%include "atmega668base.h"
%include "atmega16_32.h"
%include "attiny2313.h"

// EOF
_______________________________________________
Simulavr-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/simulavr-devel

Reply via email to