C libraries for the mMIPS NOC

There are two C libraries that help create and debug C code for the mMIPS NOC: stdcomm and mtools. Together they will be referred to as noctools. The stdcomm library implements a message passing communication protocol and mtools supports simple debugging using a printf() variant. The libraries can be compiled for both the mMIPS (using lcc) and the PC/i386 platform (using gcc). In the latter case printf() sends its output to stdout and the message passing functions read from input.bin and output to output_to_0xXXYY.bin. The libraries are located in the folder ./c_prog/noctools of the package.

Index

1. C message passing library (stdcomm)
1.1. Send data
1.2. Receive data
1.3. Debugging
1.4. Target platform selection
1.5. Functions
1.6. Variables and preprocessor symbols
2. mMIPS library (mtools)
2.1. Functions and preprocessor symbols
2.2. Target platform selection
3. Include and compile

1. C message passing library (stdcomm)

The files stdcomm.h and stdcomm.c discussed here contain the interface and implementation of a simple message passing library for the networked mMIPS. The network interface hardware supports memory mapped, packet based communication. Message passing was chosen because it integrates very well with this type of hardware communication, resulting the smallest possible development and performance overhead costs. Message passing is discussed in paragraphs 1.1. and 1.2. Paragraph 1.3 explains how to log all communication using the function mprintf() of the library mtools. Paragraph 1.4 explains and motivates the support of the library for the PC/i386. Paragraphs 1.5 and 1.6 give a full list of all the functions, variables and preprocessor symbols that make up the interface of the library.

1.1. Send data

int sc_send(const int address, const void *data, const int size_in_bytes);

Use sc_send() to send data and not sc_send_word() because the former encapsulates the internals of the communication with the network interface and the latter does not. The first argument address is the relative address of the target processor. Bits [15:8] are the X distance, bits [7:0] the Y distance (see the mMIPS network interface for more information). The network is a torus network with E-cube routing. A packet first travels over the X dimension and then over the Y dimension. The X or Y distance is decreased with one for each node visited. The target processor has been reached when both X and Y distance are zero. Packets wrap at the edges of the torus, so a node in a X by Y torus could theoretically sent itself a message by sending to address (X,Y), (X,0), (0,Y) or (0,0).

The parameter data of sc_send() is a void pointer to the data that needs to be sent. The size of this structure is set with the size_in_bytes parameter. Packets can be any integer size range from 1 to 232-1 inclusive.

The global variable try_count_sc_send determines the number of tries before sc_send() gives up and returns. sc_send() uses sc_send_word() to send each 4 byte fraction of data. The retry counter is reset whenever such a fraction has been sent successfully. If you set try_count_sc_send to zero then sc_send() is a blocking send that retries indefinitely.

The return value of sc_send() contains the number of bytes that was actually sent.

1.2. Receive data

The function sc_receive() is used for receiving data. The parameters address, data, and size_in_bytes are the same as for sc_send(). The global variable try_count_sc_receive determines the behavior of sc_receive() completely similar to the way try_count_sc_send determines the behavior of sc_send().

1.3. Debug

If the DEBUGMODE preprocessor symbol has been defined then a text string is printed using mprintf() each time to sc_receive_word() or sc_receive_word() has been called. mprintf() is defined in the mMIPS library mtools.h.

1.4. Target platform selection

The preprocessor symbol CC_I386 determines the target platform: PC/i386 or mMIPS. The PC/i386 platform is useful in the development phase of a program, because:

See the application design flow for a more complete comparison between the mMIPS platform (FPGA implementation and hardware simulator) and the PC/i386 option (referred to as "IDE" there).

mMIPS (CC_I386 is NOT defined)
If the preprocessor symbol CC_I386 has not been defined, then the communications library operates in native mMIPS mode and an attempt is made to actually send or receive data using the network interface of the mMIPS.

PC/i386 (CC_I386 is defined)
If the preprocessor symbol CC_I386 has been defined then data is read from the file input.bin and output to the file output_to_0xXXYY.bin, where XXYY is the hexadecimal representation of the 16 least significant bits of the destination address passed to sc_send(). The program is stopped with an error message if the in- or output file could not be opened. Reading beyond the end of input.bin does not stop the program. If the preprocessor symbol DEBUGMODE is defined any transmission or reception (failure) is print to stdout using mprintf().

1.5. Functions

This section presents the interface of the send and receive primitives. Check stdcomm.h for the full interface details.

Function int sc_send(const int address, const void *data, const int size_in_bytes);
Description Tries to send a block of size_in_bytes bytes. Uses sc_send_word() to send each 4 byte word in data. The maximum retry_count for each call to sc_send_word() is given by try_count_sc_send.
Return value The number of bytes that was successfully sent.

Function int sc_send_word(const int *ctrlword, const int *data, int try_count);
Description Tries to send the 32 bit word data. Checks if the network interface is ready to accept the packet and if so sends it. Retries a maximum of try_count-1 times before it returns. Use sc_send() instead of sc_send_word() to avoid setting and checking the control word ctrlword yourself.
Return value One of the predefined error values or SC_COMMERR_SUCCESS if the operation completed successfully.

Function int sc_receive(void *data, const int size_in_bytes);
Description Tries to receive a block of size_in_bytes bytes. Uses sc_receive_word() to receive each 4-byte fragment of data. The maximum retry_count for each call to sc_receive_word() is given by try_count_sc_receive.
Return value Returns the number of bytes that were successfully sent or minus size_in_bytes if the rcv_eop bit was not set after the last call to sc_receive_word().

Function int sc_receive_word(int *ctrlword, int *data, int try_count);
Description Tries to receive a 32 bit word data. Checks if the receiver is ready and then reads the 32 bit word in data if that is the case. Retries a maximum of try_count-1 times before it returns. Use sc_receive() instead of sc_receive_word() to avoid setting and checking the control word ctrlword yourself.
Return value One of the predefined error values or SC_COMMERR_SUCCESS if the operation completed successfully.

1.6. Variables and preprocessor symbols

This section presents an overview of the variables and preprocessor symbols in stdcomm.h. Check stdcomm.h for the full interface details.

#define DEBUGMODE - Prints any send or receive using mprintf() if defined. Effective on both mMIPS and PC platforms.
#define DEBUG2FILE - Any data sent is appended to the file output.bin and any data that should have been received is expected in input.bin. Effective only on the PC/i386 platform.
int try_count_sc_send
int try_count_sc_receive
- Determines how many attempts will be made to resend / receive a 4-byte block. -1 results in infinite retries.
int sc_my_address - The address of this node. Reserved.
#define SC_ - The preprocessor symbols SC_ that are used as error codes and bit masks.

2. mMIPS mtools library (mtools)

The mMIPS library enables simple debugging and implements functions that are specific to the mMIPS. The mtools library consists of the files mtools.h, mtools.c and require sprintf.h, sprintf.c and stdarg_mm.h. The sprintf files and stdarg_mm.h is are required for the function mprintf(). They contain svprintf(), which is equivalent to the standard function vprintf() with the difference that the former outputs to a memory location and the latter to stdout. The target platform of the library is PC/i386 if the preprocessor symbol CC_I386 is defined and mMIPS otherwise.

2.1. Functions and preprocessor symbols

The library consists of the following functions.

Function int mprintf (char *format, ...);
Description * On the mMIPS (preprocessor symbol CC_I386 is not defined):
Operates similar to printf(), but outputs the resulting string to a rotating memory store in the address range from MPRINTF_START_ADDR up to and including MPRINTF_MAX_ADDR. When MPRINTF_MAX_ADDR is reached then the wrap around counter is increased. If it is less than or equal to MPRINTF_WRAP_COUNT, then mprintf() continues at MPRINTF_START_ADDR, overwriting existing data. Otherwise mprintf() does nothing. Any single output may not be more than MPRINTF_BUFFER_SIZE characters long (including the trailing zero). Memory corruption may result if it does exceed that size. All preprocessor symbols (in capitals) are defined in mprintf.h.

* On the PC/i386 (CC_I386 is defined):
Uses a printf() variant (vfprintf()) to output to stdout.
Return value Always returns 0.

Function void print4bytes(const void *data);
Description Saves the first 4 bytes of the data pointed to by data in both hexadecimal and ASCII format using mprintf(). The output has the form "0x******** (....)", where the stars are replaced by hexadecimal digits and the periods by ASCII characters. The bytes are output in the exact order as they are present in memory, so no little / big endian byte reordering takes place.

Function void dump4bytes(char *buffer, const void *data);
Description Saves the first 4 bytes of the data pointed to by data in both hexadecimal and ASCII format to buffer. See also print4bytes().

Function void mt_halt(void);
Description * On the mMIPS (CC_I386 is not defined):
Starts an infinite loop.

* On the PC/i386 (CC_I386 is defined):
Calls exit(0).

Function void mt_delay(int loop_count);
Description Delays the processor by doing loop_count iterations of an empty for.

When the mtools library is used on the mMIPS platform, then four preprocessor symbols need to be set for mprintf() to work correctly:

#define Result (effective only on the mMIPS platform; no effect on the PC/i386 platform)
MPRINTF_START_ADDR This is the address where mprintf() starts writing.
MPRINTF_MAX_ADDR This is the last byte address location where mprintf() is allowed to write.
MPRINTF_WRAP_COUNT If mprintf() has reached MPRINTF_MAX_ADDR and the wrap count MPRINTF_WRAP_COUNT has not been reached, then writing continues at MPRINTF_START_ADDR.
MPRINTF_BUFFER_SIZE mprintf() temporarily stores the formatted output to a buffer of MPRINTF_BUFFER_SIZE bytes in size (200 bytes by default). If the formatted output is greater than this value, then data corruption may result. The user is responsible for ensuring the buffer is large enough.

2.2. Target platform selection

As with the communications library, the target platform can be PC/i386 or mMIPS.

3. Include and compile

Before you can use the libraries, they need to be compiled for your system. This paragraph explains how to do that. When this procedure is complete, simply adding a  #include "stdcomm.h" and #include "mtools.h" statement to your source code is sufficient to make the libraries available. There are two ways to compile the libraries:

  1. Copy sources to application directory
    Copy all individual C source files (*.c and *.h) in ./c_prog/noctools/src to root of your application so that the compiler will find them;
  2. Set up a centralized and pre-compiled version
    Compile the library once and link this centralized version of the library with your program.

The second option is the safest and this procedure is described in the paragraph "Set up centralized library". The compilation scripts dolcc and dogcc in the example applications gossip and the multi-processor JPEG decoder assume a centralized library at location pointed to by the environment variable NOCTOOLS (e.g. ~/mmips_noc/c_prog/noctools).

Set up centralized library

  1. Define NOCTOOLS
    Set the environment variable called NOCTOOLS in your logon script. The variable should contain the location of the folder ./c_prog/noctools. If you extracted the download package in your home directory then this location would be ~/mmips_noc/c_prog/noctools (~ is a shorthand notation for /home/you_home_dir). Which file is you logon script depends on the shell you get when you log on. You can determine which logon shell you have by typing ps (which gives a list of running processes) directly after you have logged on to an Linux server (info on logging on to Linux from Windows). If bash is in this list, then this should be your logon shell and ~/.bashrc should be your personal logon script. Include the command export NOCTOOLS=~/mmips_noc/c_prog/noctools in this file (create this file if it does not exist). If you see csh or tcsh in the list then you should include the command setenv NOCTOOLS ~/mmips_noc/c_prog/noctools in the logon script ~/.cshrc (create this file if it does not exist).
  2. Compile the centralized library
    If you have not set up lcc yet, do so now. Go to the directory NOCTOOLS and type make clean. Then compile the mtools and stdcomm libraries for both i386/PC (in NOCTOOLS/i386) and mMIPS (in NOCTOOLS/mmips) by choosing one of the following commands:
     
    Command Result
    make debug The preprocessor symbols DEBUGMODE and DEBUG2FILE. They have the following impact:
    • DEBUGMODE (mMIPS and PC): debugging information is generated using mprintf() with every send and receive;
    • DEBUG2FILE (PC only): any data sent is appended to the file output.bin and any data that should have been received is expected in input.bin.
    make release Defines only DEBUG2FILE and not DEBUGMODE. This increases the speed of the library.
  3. Add #include "stdcomm.h" and #include "mtools.h" to the source code that requires the libraries.
  4. As said before, the  i386/PC version of the libraries are in NOCTOOLS/i386 and the mMIPS versions are in NOCTOOLS/mmips. Below are two examples of the command lines that can be used to compile gossip.c which uses the libraries (using the syntax of the bash shell):
     
    Platform Command
    Linux (i386 using gcc) gcc -g -ansi -pedantic $(I386) -Wall -O -o gossip -I$(NOCTOOLS)/src -L$(NOCTOOLS)/i386 -lmtools -lstdcomm -lsprintf -lm gossip
    NOC (mMIPS using lcc) lcc -N -AA -o gossip -I$NOCTOOLS/src -L$NOCTOOLS/mmips -lmtools -lstdcomm -lsprintf gossip.c

    Note: these commands were copied from the scripts dolcc and dogcc and are executed by bash (even if that is not the current shell).

  5. Run your program from the command line, copy it to the FPGA or simulate it on the hardware simulator.  See the application design flow for information on how to compile, debug, simulate or upload applications.

The difference between the libraries in i386 and mMIPS is that the former is compiled using gcc with the preprocessor symbol CC_I386 defined and the latter with lcc without CC_I386. See the Makefile for more information.