gnupic: gpsim logging writes to IO ports


Previous by date: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden
Next by date: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden
Previous in thread: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden
Next in thread: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden

Subject: Re: gpsim logging writes to IO ports
From: Scott Dattalo ####@####.####
Date: 9 Feb 2003 14:05:32 -0000
Message-Id: <Pine.LNX.4.44.0302090511300.19663-100000@ruckus.brouhaha.com>

On 9 Feb 2003, Alex Holden wrote:

> On Sat, 2003-02-08 at 22:42, Alex Holden wrote:
> > I've just been messing about with the CVS version of gpsim, and I tried
> > to use the log facility to log all writes to an IO port, but it didn't
> > log anything at all. Telling it to log writes to an ordinary memory
> > register instead worked as expected. Is this a bug, and if so how would
> > I go about fixing it?
> 
> Doh, after poring over the gpsim source code for an hour I realised that
> it was working all along. Two things confused me into thinking it wasn't
> working when actually it was:
> 
> * There are two symbols defined for the 12c509, gpio (ioport 0) and GPIO
> (constant 0x06), and only the upper case one works.
> * gpsim.log is backed by quite a large buffer so it typically remains
> empty until you do a "log off" or quit gpsim. It worked when I set it to
> log writes to a loop counter variable because it generated so many
> writes that it flushed the buffer almost straight away.

I'm glad you got it resolved!

> 
> Now I'm attempting to write a module with very little experience of
> coding in C++. I don't suppose anyone's written a "subtitles for the
> hard of thinking" guide to writing gpsim modules have they? I want my
> module to be able to:
> 
> * Watch the state of some digital input pins, and read the cycle counter
> when they change.
> * Get called every "n" processor simulation cycles (or getting called
> once every cycle would do) to do some background simulation work, and be
> able to read the processor cycle counter from here also.
> * Control the state of some digital output pins from the background
> simulation.
> * Write data to the log (Ok, the module itself could open a file and log
> to it, but it'd be nicer to use the Gpsim log facility).
> * Get notified when the processor has been reset so I can also reset my
> simulation.


All of these except for possible the reset is possible.

I'd suggest as a good working example the code for usart.cc:

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/gpsim/modules/usart.cc

Originally I wrote the module interface with the idea that gpsim's API 
would be totally abstracted. In fact, the whole gui was originally 
implemented this way (and still mostly is implemented this way). But, 
there are many, many features buried deeply within gpsim that just don't 
make sense to abstract. Further more, there really is no reason for the 
abstraction (the original reason was that the gui was written in C, but 
the simulation engine was in C++).

The simulation engine of gpsim is built into a library. If you wanted to 
build your own custom simulator, you could strip away the CLI and the GUI 
and link directly against libgpsim. That would be a whole lot of work 
however. But the main reason for having libgpsim is that the external 
modules know the interface to gpsim. For example, along with installing 
libgpsim, the config scripts also install all of the include files. So, 
there's no reason why you can't link against these!

So in the usart.cc module, that's what I've done:

#include "../src/attribute.h"
#include "../src/modules.h"
#include "../src/packages.h"
#include "../src/stimuli.h"
#include "../src/ioports.h"
#include "../src/symbol.h"
#include "../src/interface.h"

This exposes the guts of gpsim to the usart.cc code. So the pic processor 
base class is fully exposed to you, the programmer.

Another example that is probably more useful is the LCD module. The reason 
is that it is a stand alone module. The configuration scripts know how to 
search for the presence of gpsim and automagically provide paths to the 
libraries and include files. See:

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/gpsim/extras/lcd/

This allows you to write the includes like:

#include <gpsim/stimuli.h>
#include <gpsim/ioports.h>
#include <gpsim/symbol.h>
#include <gpsim/trace.h>

-----------

Some specific examples...

You can get total control of your module's I/O pins by creating a new 
class derived from gpsim IO pin classes. For example,

class USART_TXPIN : public IO_bi_directional

Creates a new class type for the USART Tx Pin. It's based on gpsim's 
bi-directional IO pin class (which is defined in stimuli.h). Since all of 
the member functions in the IO_bi_directional class are virtual, you can 
easily override them (or not) with your own custom function. 

The IO_bi_directional class is actually a class derived from the IOPIN 
(which is a class derived from stimuli). So all of these functions are 
available for re-definition:

  virtual int get_voltage(guint64 current_time) {return state;};
  virtual int get_state(void);
  virtual file_register *get_iop(void);
  virtual void put_state(int new_state) {state=new_state;}; 
  virtual void put_node_state(int new_state) {state=new_state;}; // From 
attached node
  virtual void put_state_value(int new_state);
  virtual void toggle(void) {state = !state;}; 
  virtual void attach(Stimulus_Node *s);
  virtual void change_direction(unsigned int){return;};
  virtual void update_direction(unsigned int x){return;};

At this point, the obvious question is "what do these functions do?". 
Unfortunately, except for the comments in the source code, I haven't 
documented gpsim's api. Which is why at the beginning I referred you to 
usart.cc and lcd.cc.

For example, here's the USART_TXPIN overriding ::put_state which is a 
function that get's called when an I/O pin decides to update it's "state":
 
  void put_state( int new_digital_state) {

    file_register *port = get_iop();

    if(port) {
      // If the new state to which the stimulus is being set is different 
than
      // the current state of the bit in the ioport (to which this 
stimulus is
      // mapped), then we need to update the ioport.

      if((new_digital_state!=0) ^ ( port->value & (1<<iobit))) {

	port->setbit(iobit,new_digital_state);

	digital_state = new_digital_state;
	// If this stimulus is attached to a node, then let the node be 
updated
	// with the new state as well.
	if(snode)
	  snode->update(0);
	// Note that this will auto magically update
	// the io port.

      }
    }

--------

To get cyclic response, you'll need to define an object derived from the
BreakCallBack class. gpsim has a function call-back mechanism that is
based on the simulator's cycle counter. A function can be programmed to be
called when the cycle counter reaches a certain value. (The cycle counter
is a 64-bit counter that advances by one count for every PIC cpu cycle. 
The reason that it's 64 instead of 32 bits is that the latter gives you 
*only* 4 billion simulation cycles which is something like 7 minutes of 
run time in a 20 Mhz PIC). 

I typically define registers derived from the BreakCallBack class (in fact 
all SFR's are defined that way). For example, from the usart.cc code the 
Transmit Register is defined like so:

 class TXREG : public BreakCallBack


The key function is:

  virtual void callback(void) 

This function is defined in the BreakCallBack class and can be overridden 
by your special register definition. All you need to do to use it is to 
set a "cyclic break point". This is done by calling:

  gpsim_set_break()

For example:

    last_time = gpsim_get_current_time();
    future_time = last_time + time_per_bit * 12;
    gpsim_set_break(future_time, this);

This snippet reads the current time and sets a new break point in the 
future. When the simulation cycle counter reaches "future_time", the 
function "callback" will get called. 

-------

okay, that oughta be enough for now...

Scott




Previous by date: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden
Next by date: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden
Previous in thread: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden
Next in thread: 9 Feb 2003 14:05:32 -0000 Re: gpsim logging writes to IO ports, Alex Holden


Powered by ezmlm-browse 0.20.