If the application need is: Master has to read/write starting from any arbitrary part of the I2C buffer(this arbitrary index will be sent by the master before every read/write cycle) then EzI2C is the preferred user module. All I2C operations will be handled in interrupts inbuilt within the EzI2C slave user module.
If the need of the PSoC application is ANYTHING other than this(it could be simpler or more complex than the above) like
1) simpler - eg: master just reads/writes to buffer without sending index
2) complex - eg: master needs to read from a particular buffer which depends upon what values were written into a set of write buffers
For these applications, we need more flexibility and hence we must poll(the I2C status flags) for completion of read/write cycle and perform operations(such as initializing
read/write buffers to appropriate values as per application need) in that polling routine.
PRECAUTION: The frequency of polling must be in such a way that ,say, the read/write buffers are initialized prior to the future I2C operations that expect the initializations to read/write buffers. This timing would not be a problem if the polling of the flags was the only thing done by the application. But if the main.c code becomes long and we do not poll the flags frequently enough, then the I2C may not operate as expected. For this, a possible workaround is to include the polling routine in between chunks of main.c code and ensure that the polling occurs frequently enough.
Usually EzI2C satisfies most of the practical I2C applications. But for other cases, you may use I2CHW slave with the precaution stated above.