= The MWMR Library = [[PageOutline]] The [source:soft/giet_vm/giet_libs/mwmr_channel.c mwmr_channel.c] and [source:soft/giet_vm/giet_libs/mwmr_channel.h mwmr_channel.h] files define an user-level communication middleware, for parallel multi-threads applications. It supports channelized communications , when the communication scheme can be statically described by a Task and Communication Graph. Each MWMR (Multi-Writer Multi-Reader) channel can be accessed concurently by one or several writer(s) and by one or several reader(s). It is implemented as a software FIFO, protected by a build-in, user-level spin_lock. This software FIFO can be directly accessed by an hardware coprocessor, thanks to the vci_mwmr_controller, but we only describe here the software API that can be used by a software applications. An MWMR transaction transfer an integer number of items between a thread private buffer and the MWMR communication channel. An item is the smallest quantity of data that can be atomically transfered. It is an integer number of 32 bits words (uint32_t). An '''mwmr_channel_t''' communication channel is therefore defined by two parameters: * The '''width''' parameter define the number of words contained in an item (can be 1). * The '''nitems''' parameter define the max number of items that can be stored in the FIFO. In the user code, an MWMR channel must be defined by two global variables: * a '''channel descriptor''' is a variable of type '''mwmr_channel_t'''. * a '''data buffer''' is an array of 32 bits words. WARNING (i) The MWMR channel, can be accessed by several tasks, but it must be initialized by one single task. WARNING (ii) The channel must be declared in a non cacheable segment, if the platform does not provide hardware cache coherence. The '''mwmr_read()''' and '''mwmr_write()''' blocking functions can be used to implement a parallel application complying with the KPN (Kahn Process Network) semantic. The '''nb_mwmr_read()''' and '''nb_mwmr_write()''' non blocking functions can be used to implement various higher level communication protocols. == __Communication Channel Initialisation__ == === void '''mwmr_init'''( mwmr_channel_t* mwmr, uint32_t* buffer , uint32_t width , uint32_t items ) === This function initializes the MWMR channel descriptor (including the lock protecting exclusive access). * '''mwmr''' : MWMR channel descriptor base address. * '''buffer''' : data buffer (unsigned int) base address. * '''width''' : number of 32 bits words contained in an item. * '''nitems''' : max number of items in the channel. It must be called by one single task. == __Communication Channel Blocking Access__ == === void '''mwmr_write'''( mwmr_channel_t* mwmr, uint32_t* buffer , uint32_t items ) === This function transfer (nitems * width) 32 bits words from a task private buffer to the MWMR channel. * '''mwmr''' : MWMR channel virtual base address. * '''buffer''' : virtual base address of local buffer. * '''items''' : number of items to be transfered. It takes the lock for exclusive access before testing the channel state. If there is not enough space in mwmr channel to write nitems, it writes as many items as possible, releases the lock, does not return, but retry to take the lock to transfer the rest of the data... up to completion. === void '''mwmr_read'''( mwmr_channel_t* mwmr, uint32_t* buffer , uint32_t items ) === This function transfer (nitems * width) 32 bits words from the MWMR channel to a task private buffer. * '''mwmr''' : MWMR channel virtual base address. * '''buffer''' : virtual base address of local buffer. * '''items''' : number of items to be transfered. It takes the lock for exclusive access before testing the channel state. If there is not enough space in mwmr channel to write nitems, it writes as many items as possible, releases the lock, does not return, but retry to take the lock to transfer the rest of the data... up to completion. == __Communication Channel Non Blocking Access__ == === uint32_t '''nb_mwmr_write'''( mwmr_channel_t* mwmr , uint32_t* buffer , uint32_t items ) === This function request to transfer (nitems * width) 32 bits words from a task private buffer tot he MWMR channel. * '''mwmr''' : MWMR channel virtual base address. * '''buffer''' : virtual base address of local buffer. * '''items''' : number of items to be transfered. It takes the lock for exclusive access before testing the channel state. If there is not enough free space in the channel, it transfer as many items as possible, releases the lock, and returns the number of actually transfered items (it can be 0). === uint32_t '''nb_mwmr_write'''( mwmr_channel_t* mwmr , uint32_t* buffer , uint32_t items ) === This function request to transfer (nitems * width) 32 bits words from the MWMR channel to a task private buffer. * '''mwmr''' : MWMR channel virtual base address. * '''buffer''' : virtual base address of local buffer. * '''items''' : number of items to be transfered. It takes the lock for exclusive access before testing the channel state. If there is not enough data in the channel, it transfer as many items as possible, releases the lock, and returns the number of actually transfered items (it can be 0). Besides the MWMR channels, the MWMR library provide another - optional - service: The '''mwmr_bufio_t''' buffer (and the associated access functions) can be used to implement a private input or output buffer, and move data to or from a shared MWMR communication channel. This buffer can be declared as a local variable in the stack of the reader/writer thread, and simplifies the access to the MWMR channel when the transfered data have a non fixed format, and must be analysed or produced byte per byte: * the buffer descriptor contains a byte pointer. * an input buffer is automatically refill from the associated MWMR channel when it becomes empty. * an output buffer is automatically transferred to the associated MWMR channel when it becomes full. == __Private Buffer Initialization__ == === void '''mwmr_bufio_init'''( mwmr_bufio_t* bufio , uint8_t* buffer , uint32_t size , uint32_t is_input , mwmr_channel_t* mwmr ) === This function initializes the BUFIO descriptor. * '''bufio''' : pointer on the BUFIO descriptor. * '''buffer''' : pointer on the private buffer. * '''size''' : number of bytes in the private buffer / must be multiple of 4. * '''is_input''' : buffer type / input buffer when non-zero. * '''mwmr''' : pointer on the associated MWMR channel descriptor. === void '''mwmr_bufio_reset'''( mwmr_bufio_t* bufio ) === This function reset the BUFIO byte pointer, to discard all bytes contained in the BUFIO. == __Private Input Buffer Access__ == === uint8_t '''mwmr_bufio_read_byte'''( mwmr_bufio_t* bufio ) === This blocking function returns one single byte from the MWMR channel associated to the input buffer. === uint16_t '''mwmr_bufio_read_half'''( mwmr_bufio_t* bufio ) === This blocking function returns two bytes from the MWMR channel associated to the input buffer. === uint32_t '''mwmr_bufio_read_word'''( mwmr_bufio_t* bufio ) === This blocking function returns four bytes from the MWMR channel associated to the input buffer. === void '''mwmr_bufio_skip'''( mwmr_bufio_t* bufio , uint32_t length ) === This function discard bytes from the MWMR channel associated to the input buffer. == __Private Output Buffer Access__ == === void '''mwmr_bufio_write_byte'''( mwmr_bufio_t* bufio , uint8_t value ) === This blocking function writes one byte into the MWMR channel associated to the output buffer. === void '''mwmr_bufio_write_half'''( mwmr_bufio_t* bufio , uint16_t value ) === This blocking function writes two bytes into the MWMR channel associated to the output buffer. === void '''mwmr_bufio_write_word'''( mwmr_bufio_t* bufio , uint32_t value ) === This blocking function writes four bytes into the MWMR channel associated to the output buffer. === void '''mwmr_bufio_flush'''( mwmr_bufio_t* bufio ) === This function moves the current content of the output buffer to the associated MWMR channel when it is non empty. It introduces padding zeros if the number of bytes contained in the bufio is not multiple of the item size.