diff --git a/axi/simlink/src/RogueSideBand.c b/axi/simlink/src/RogueSideBand.c index 2cc2104368..8bcd633ec0 100755 --- a/axi/simlink/src/RogueSideBand.c +++ b/axi/simlink/src/RogueSideBand.c @@ -25,203 +25,202 @@ // Start/resetart zeromq server void RogueSideBandRestart(RogueSideBandData *data, portDataT *portData) { - char buffer[100]; + char buffer[100]; - if ( data->zmqPush != NULL ) zmq_close(data->zmqPush ); - if ( data->zmqPull != NULL ) zmq_close(data->zmqPull); - if ( data->zmqCtx != NULL ) zmq_term(data->zmqCtx); + if ( data->zmqPush != NULL ) zmq_close(data->zmqPush ); + if ( data->zmqPull != NULL ) zmq_close(data->zmqPull); + if ( data->zmqCtx != NULL ) zmq_term(data->zmqCtx); - data->zmqCtx = NULL; - data->zmqPush = NULL; - data->zmqPull = NULL; + data->zmqCtx = NULL; + data->zmqPush = NULL; + data->zmqPull = NULL; - data->zmqCtx = zmq_ctx_new(); - data->zmqPull = zmq_socket(data->zmqCtx, ZMQ_PULL); - data->zmqPush = zmq_socket(data->zmqCtx, ZMQ_PUSH); + data->zmqCtx = zmq_ctx_new(); + data->zmqPull = zmq_socket(data->zmqCtx, ZMQ_PULL); + data->zmqPush = zmq_socket(data->zmqCtx, ZMQ_PUSH); - vhpi_printf("RogueSideBand: Listening on ports %i & %i\n", data->port, data->port+1); + vhpi_printf("RogueSideBand: Listening on ports %i & %i\n", data->port, data->port+1); - snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port+1); - if ( zmq_bind(data->zmqPull, buffer) ) { - vhpi_assert("RogueSideBand: Failed to bind sideband port", vhpiFatal); - return; - } + snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port+1); + if ( zmq_bind(data->zmqPull, buffer) ) { + vhpi_assert("RogueSideBand: Failed to bind sideband port", vhpiFatal); + return; + } - snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port); - if ( zmq_bind(data->zmqPush, buffer) ) { - vhpi_assert("RogueSideBand: Failed to bind push port", vhpiFatal); - return; - } + snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port); + if ( zmq_bind(data->zmqPush, buffer) ) { + vhpi_assert("RogueSideBand: Failed to bind push port", vhpiFatal); + return; + } } // Send a message void RogueSideBandSend(RogueSideBandData *data, portDataT *portData) { - zmq_msg_t msg; - uint8_t ba[4]; - char buffer[200]; - - if ( (zmq_msg_init_size(&msg, 4) < 0) ) { - vhpi_assert("RogueSideBand: Failed to init message", vhpiFatal); - return; - } - - ba[0] = data->txOpCodeEn; - ba[1] = data->txOpCode; - ba[2] = data->txRemDataChanged; - ba[3] = data->txRemData; - - memcpy(zmq_msg_data(&msg), ba, 4); - - // Send data - if ( zmq_msg_send(&msg, data->zmqPush, 0) < 0 ) { - snprintf(buffer, sizeof(buffer), "RogueSideBand: Failed to send opcode: %x, remData: %x, on port %i\n", data->txOpCode, data->txRemData, data->port); - vhpi_assert(buffer, vhpiFatal); - } - if (data->txOpCodeEn) { - vhpi_printf("%lu RogueSideBand: Sent Opcode: %x on port %i\n", portData->simTime, data->txOpCode, data->port); - } - if (data->txRemDataChanged) { - vhpi_printf("%lu RogueSideBand: Sent remData: %x on port %i\n", portData->simTime, data->txRemData, data->port); - } + zmq_msg_t msg; + uint8_t ba[4]; + char buffer[200]; + + if ( (zmq_msg_init_size(&msg, 4) < 0) ) { + vhpi_assert("RogueSideBand: Failed to init message", vhpiFatal); + return; + } + + ba[0] = data->txOpCodeEn; + ba[1] = data->txOpCode; + ba[2] = data->txRemDataChanged; + ba[3] = data->txRemData; + + memcpy(zmq_msg_data(&msg), ba, 4); + + // Send data + if ( zmq_msg_send(&msg, data->zmqPush, 0) < 0 ) { + snprintf(buffer, sizeof(buffer), "RogueSideBand: Failed to send opcode: %x, remData: %x, on port %i\n", data->txOpCode, data->txRemData, data->port); + vhpi_assert(buffer, vhpiFatal); + } + if (data->txOpCodeEn) { + vhpi_printf("%lu RogueSideBand: Sent Opcode: %x on port %i\n", portData->simTime, data->txOpCode, data->port); + } + if (data->txRemDataChanged) { + vhpi_printf("%lu RogueSideBand: Sent remData: %x on port %i\n", portData->simTime, data->txRemData, data->port); + } } // Receive side data if it is available int RogueSideBandRecv(RogueSideBandData *data, portDataT *portData) { - uint8_t * rd; - uint32_t rsize; - zmq_msg_t rMsg; - - zmq_msg_init(&rMsg); - if ( zmq_msg_recv(&rMsg, data->zmqPull, ZMQ_DONTWAIT) <= 0 ) { - zmq_msg_close(&rMsg); - return(0); - } - - rd = zmq_msg_data(&rMsg); - rsize = zmq_msg_size(&rMsg); - - if ( rsize == 4 ) { - if ( rd[0] == 0x01 ) { - data->rxOpCode = rd[1]; - data->rxOpCodeEn = 1; - vhpi_printf("%lu RogueSideBand: Got opcode 0x%0.2x on port %i\n", portData->simTime, data->rxOpCode, data->port+1); - } - if ( rd[2] == 0x01 ) { - data->rxRemData = rd[3]; - vhpi_printf("%lu RogueSideBand: Got data 0x%0.2x on port %i\n", portData->simTime, data->rxRemData, data->port+1); - } - } - zmq_msg_close(&rMsg); - return(rsize); + uint8_t * rd; + uint32_t rsize; + zmq_msg_t rMsg; + + zmq_msg_init(&rMsg); + if ( zmq_msg_recv(&rMsg, data->zmqPull, ZMQ_DONTWAIT) <= 0 ) { + zmq_msg_close(&rMsg); + return(0); + } + + rd = zmq_msg_data(&rMsg); + rsize = zmq_msg_size(&rMsg); + + if ( rsize == 4 ) { + if ( rd[0] == 0x01 ) { + data->rxOpCode = rd[1]; + data->rxOpCodeEn = 1; + vhpi_printf("%lu RogueSideBand: Got opcode 0x%0.2x on port %i\n", portData->simTime, data->rxOpCode, data->port+1); + } + if ( rd[2] == 0x01 ) { + data->rxRemData = rd[3]; + vhpi_printf("%lu RogueSideBand: Got data 0x%0.2x on port %i\n", portData->simTime, data->rxRemData, data->port+1); + } + } + zmq_msg_close(&rMsg); + return(rsize); } // Init function void RogueSideBandInit(vhpiHandleT compInst) { - // Create new port data structure - portDataT *portData = (portDataT *) malloc(sizeof(portDataT)); - RogueSideBandData *data = (RogueSideBandData *) malloc(sizeof(RogueSideBandData)); + // Create new port data structure + portDataT *portData = (portDataT *) malloc(sizeof(portDataT)); + RogueSideBandData *data = (RogueSideBandData *) malloc(sizeof(RogueSideBandData)); - // Get port count - portData->portCount = PORT_COUNT; + // Get port count + portData->portCount = PORT_COUNT; - // Set port directions - portData->portDir[s_clock] = vhpiIn; - portData->portDir[s_reset] = vhpiIn; - portData->portDir[s_port] = vhpiIn; + // Set port directions + portData->portDir[s_clock] = vhpiIn; + portData->portDir[s_reset] = vhpiIn; + portData->portDir[s_port] = vhpiIn; - portData->portDir[s_txOpCode] = vhpiIn; - portData->portDir[s_txOpCodeEn] = vhpiIn; - portData->portDir[s_txRemData] = vhpiIn; + portData->portDir[s_txOpCode] = vhpiIn; + portData->portDir[s_txOpCodeEn] = vhpiIn; + portData->portDir[s_txRemData] = vhpiIn; - portData->portDir[s_rxOpCode] = vhpiOut; - portData->portDir[s_rxOpCodeEn] = vhpiOut; - portData->portDir[s_rxRemData] = vhpiOut; + portData->portDir[s_rxOpCode] = vhpiOut; + portData->portDir[s_rxOpCodeEn] = vhpiOut; + portData->portDir[s_rxRemData] = vhpiOut; - // Set port widths - portData->portWidth[s_clock] = 1; - portData->portWidth[s_reset] = 1; - portData->portWidth[s_port] = 16; + // Set port widths + portData->portWidth[s_clock] = 1; + portData->portWidth[s_reset] = 1; + portData->portWidth[s_port] = 16; - portData->portWidth[s_txOpCode] = 8; - portData->portWidth[s_txOpCodeEn] = 1; - portData->portWidth[s_txRemData] = 8; + portData->portWidth[s_txOpCode] = 8; + portData->portWidth[s_txOpCodeEn] = 1; + portData->portWidth[s_txRemData] = 8; - portData->portWidth[s_rxOpCode] = 8; - portData->portWidth[s_rxOpCodeEn] = 1; - portData->portWidth[s_rxRemData] = 8; + portData->portWidth[s_rxOpCode] = 8; + portData->portWidth[s_rxOpCodeEn] = 1; + portData->portWidth[s_rxRemData] = 8; - // Create data structure to hold state - portData->stateData = data; + // Create data structure to hold state + portData->stateData = data; - // State update function - portData->stateUpdate = *RogueSideBandUpdate; + // State update function + portData->stateUpdate = *RogueSideBandUpdate; - // Init - memset(data, 0, sizeof(RogueSideBandData)); + // Init + memset(data, 0, sizeof(RogueSideBandData)); - // Call generic Init - VhpiGenericInit(compInst, portData); + // Call generic Init + VhpiGenericInit(compInst, portData); } - // User function to update state based upon a signal change void RogueSideBandUpdate(void *userPtr) { - portDataT *portData = (portDataT*) userPtr; - RogueSideBandData *data = (RogueSideBandData*)(portData->stateData); - uint8_t send = 0; - - // Detect clock edge - if ( data->currClk != getInt(s_clock) ) { - data->currClk = getInt(s_clock); - - // Rising edge - if ( data->currClk ) { - // Reset is asserted - if ( getInt(s_reset) == 1 ) { - data->rxRemData = 0x00; - data->rxOpCode = 0x00; - data->rxOpCodeEn = 0; - data->txRemData = 0x00; - data->txRemDataChanged = 0x00; - data->txOpCode = 0x00; - data->txOpCodeEn = 0; - setInt(s_rxOpCodeEn, 0); - setInt(s_rxOpCode, 0); - setInt(s_rxRemData, 0); - - // Out of reset - } else { - // Port not yet assigned - if ( data->port == 0 ) { - data->port = getInt(s_port); - RogueSideBandRestart(data, portData); - } - - // TX OpCode - if (getInt(s_txOpCodeEn)) { - data->txOpCode = getInt(s_txOpCode); - data->txOpCodeEn = getInt(s_txOpCodeEn); - send = 1; - } - - // TX RemData - if (getInt(s_txRemData) != data->txRemData) { - data->txRemData = getInt(s_txRemData); - data->txRemDataChanged = 1; - send = 1; - } - - if (send) { - RogueSideBandSend(data, portData); + portDataT *portData = (portDataT*) userPtr; + RogueSideBandData *data = (RogueSideBandData*)(portData->stateData); + uint8_t send = 0; + + // Detect clock edge + if ( data->currClk != getInt(s_clock) ) { + data->currClk = getInt(s_clock); + + // Rising edge + if ( data->currClk ) { + // Reset is asserted + if ( getInt(s_reset) == 1 ) { + data->rxRemData = 0x00; + data->rxOpCode = 0x00; + data->rxOpCodeEn = 0; + data->txRemData = 0x00; + data->txRemDataChanged = 0x00; + data->txOpCode = 0x00; + data->txOpCodeEn = 0; + setInt(s_rxOpCodeEn, 0); + setInt(s_rxOpCode, 0); + setInt(s_rxRemData, 0); + + // Out of reset + } else { + // Port not yet assigned + if ( data->port == 0 ) { + data->port = getInt(s_port); + RogueSideBandRestart(data, portData); + } + + // TX OpCode + if (getInt(s_txOpCodeEn)) { + data->txOpCode = getInt(s_txOpCode); + data->txOpCodeEn = getInt(s_txOpCodeEn); + send = 1; + } + + // TX RemData + if (getInt(s_txRemData) != data->txRemData) { + data->txRemData = getInt(s_txRemData); + data->txRemDataChanged = 1; + send = 1; + } + + if (send) { + RogueSideBandSend(data, portData); + } + + // Rx Data + RogueSideBandRecv(data, portData); + setInt(s_rxRemData, data->rxRemData); + setInt(s_rxOpCode, data->rxOpCode); + setInt(s_rxOpCodeEn, data->rxOpCodeEn); + data->rxOpCodeEn = 0; // Only for one clock } - - // Rx Data - RogueSideBandRecv(data, portData); - setInt(s_rxRemData, data->rxRemData); - setInt(s_rxOpCode, data->rxOpCode); - setInt(s_rxOpCodeEn, data->rxOpCodeEn); - data->rxOpCodeEn = 0; // Only for one clock - } - } - } + } + } } diff --git a/axi/simlink/src/RogueTcpMemory.c b/axi/simlink/src/RogueTcpMemory.c index 19dd5fbc63..bbf5a0dca4 100755 --- a/axi/simlink/src/RogueTcpMemory.c +++ b/axi/simlink/src/RogueTcpMemory.c @@ -25,341 +25,340 @@ // Start/resetart zeromq server void RogueTcpMemoryRestart(RogueTcpMemoryData *data, portDataT *portData) { - char buffer[100]; + char buffer[100]; - if ( data->zmqPush != NULL ) zmq_close(data->zmqPull); - if ( data->zmqPull != NULL ) zmq_close(data->zmqPush); - if ( data->zmqCtx != NULL ) zmq_term(data->zmqCtx); + if ( data->zmqPush != NULL ) zmq_close(data->zmqPull); + if ( data->zmqPull != NULL ) zmq_close(data->zmqPush); + if ( data->zmqCtx != NULL ) zmq_term(data->zmqCtx); - data->zmqCtx = NULL; - data->zmqPull = NULL; - data->zmqPush = NULL; + data->zmqCtx = NULL; + data->zmqPull = NULL; + data->zmqPush = NULL; - data->zmqCtx = zmq_ctx_new(); - data->zmqPull = zmq_socket(data->zmqCtx, ZMQ_PULL); - data->zmqPush = zmq_socket(data->zmqCtx, ZMQ_PUSH); + data->zmqCtx = zmq_ctx_new(); + data->zmqPull = zmq_socket(data->zmqCtx, ZMQ_PULL); + data->zmqPush = zmq_socket(data->zmqCtx, ZMQ_PUSH); - vhpi_printf("RogueTcpMemory: Listening on ports %i & %i\n", data->port, data->port+1); + vhpi_printf("RogueTcpMemory: Listening on ports %i & %i\n", data->port, data->port+1); - snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port); - if ( zmq_bind(data->zmqPull, buffer) ) { - vhpi_assert("RogueTcpMemory: Failed to bind pull port", vhpiFatal); - return; - } + snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port); + if ( zmq_bind(data->zmqPull, buffer) ) { + vhpi_assert("RogueTcpMemory: Failed to bind pull port", vhpiFatal); + return; + } - snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port+1); - if ( zmq_bind(data->zmqPush, buffer) ) { - vhpi_assert("RogueTcpMemory: Failed to bind push port", vhpiFatal); - return; - } + snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port+1); + if ( zmq_bind(data->zmqPush, buffer) ) { + vhpi_assert("RogueTcpMemory: Failed to bind push port", vhpiFatal); + return; + } } - // Send a message void RogueTcpMemorySend(RogueTcpMemoryData *data, portDataT *portData) { - uint32_t x; - zmq_msg_t msg[6]; + uint32_t x; + zmq_msg_t msg[6]; - if ( (zmq_msg_init_size(&(msg[0]), 4) < 0) || // ID + if ( (zmq_msg_init_size(&(msg[0]), 4) < 0) || // ID (zmq_msg_init_size(&(msg[1]), 8) < 0) || // Addr (zmq_msg_init_size(&(msg[2]), 4) < 0) || // Size (zmq_msg_init_size(&(msg[3]), 4) < 0) || // type (zmq_msg_init_size(&(msg[5]), 4) < 0) ) { // result - vhpi_assert("RogueTcpMemory: Failed to init message header", vhpiFatal); - return; - } - - if (zmq_msg_init_size(&(msg[4]), data->size) < 0) { - vhpi_assert("RogueTcpMemory: Failed to init message", vhpiFatal); - return; - } - - memcpy(zmq_msg_data(&(msg[0])), &(data->id), 4); - memcpy(zmq_msg_data(&(msg[1])), &(data->addr), 8); - memcpy(zmq_msg_data(&(msg[2])), &(data->size), 4); - memcpy(zmq_msg_data(&(msg[3])), &(data->type), 4); - memcpy(zmq_msg_data(&(msg[5])), &(data->result), 4); - - // Copy data - memcpy(zmq_msg_data(&(msg[4])), data->data, data->size); - - // Send data - for (x=0; x < 6; x++) { - if ( zmq_sendmsg(data->zmqPush, &(msg[x]), (x == 5)?0:ZMQ_SNDMORE) < 0 ) - vhpi_assert("RogueTcpMemory: Failed to send message", vhpiFatal); - } - data->state = 0; - data->curr = 0; - - vhpi_printf("%lu RogueTcpMemory: Send Tran: Id %i, Addr 0x%x, Size %i, Type %i, Resp 0x%x\n", portData->simTime, data->id, data->addr, data->size, data->type, data->result); + vhpi_assert("RogueTcpMemory: Failed to init message header", vhpiFatal); + return; + } + + if (zmq_msg_init_size(&(msg[4]), data->size) < 0) { + vhpi_assert("RogueTcpMemory: Failed to init message", vhpiFatal); + return; + } + + memcpy(zmq_msg_data(&(msg[0])), &(data->id), 4); + memcpy(zmq_msg_data(&(msg[1])), &(data->addr), 8); + memcpy(zmq_msg_data(&(msg[2])), &(data->size), 4); + memcpy(zmq_msg_data(&(msg[3])), &(data->type), 4); + memcpy(zmq_msg_data(&(msg[5])), &(data->result), 4); + + // Copy data + memcpy(zmq_msg_data(&(msg[4])), data->data, data->size); + + // Send data + for (x=0; x < 6; x++) { + if ( zmq_sendmsg(data->zmqPush, &(msg[x]), (x == 5)?0:ZMQ_SNDMORE) < 0 ) + vhpi_assert("RogueTcpMemory: Failed to send message", vhpiFatal); + } + data->state = 0; + data->curr = 0; + + vhpi_printf("%lu RogueTcpMemory: Send Tran: Id %i, Addr 0x%x, Size %i, Type %i, Resp 0x%x\n", portData->simTime, data->id, data->addr, data->size, data->type, data->result); } // Receive data if it is available int RogueTcpMemoryRecv(RogueTcpMemoryData *data, portDataT *portData) { - uint64_t more; - size_t moreSize; - uint32_t x; - uint32_t msgCnt; - zmq_msg_t msg[5]; - - for (x=0; x < 5; x++) zmq_msg_init(&(msg[x])); - msgCnt = 0; - x = 0; - - // Get message - do { - // Get the message - if (zmq_recvmsg(data->zmqPull, &(msg[x]), ZMQ_DONTWAIT) > 0) { - if ( x != 4 ) x++; - msgCnt++; - - // Is there more data? - more = 0; - moreSize = 8; - zmq_getsockopt(data->zmqPull, ZMQ_RCVMORE, &more, &moreSize); - } else { - more = 0; - } - } while ( more ); - - // Proper message received - if (msgCnt == 4 || msgCnt == 5) { - // Check sizes - if ( (zmq_msg_size(&(msg[0])) != 4) || (zmq_msg_size(&(msg[1])) != 8) || - (zmq_msg_size(&(msg[2])) != 4) || (zmq_msg_size(&(msg[3])) != 4) ) { - vhpi_assert("RogueTcpMemory: Bad message size", vhpiFatal); - for (x=0; x < msgCnt; x++) zmq_msg_close(&(msg[x])); - return 0; - } - - // Get fields - memcpy(&(data->id), zmq_msg_data(&(msg[0])), 4); - memcpy(&(data->addr), zmq_msg_data(&(msg[1])), 8); - memcpy(&(data->size), zmq_msg_data(&(msg[2])), 4); - memcpy(&(data->type), zmq_msg_data(&(msg[3])), 4); - - // Write data is expected - if ( (data->type == T_WRITE) || (data->type == T_POST) ) { - if ( (msgCnt != 5) || (zmq_msg_size(&(msg[4])) != data->size) ) { - vhpi_assert("RogueTcpMemory: Transaction write data error", vhpiFatal); + uint64_t more; + size_t moreSize; + uint32_t x; + uint32_t msgCnt; + zmq_msg_t msg[5]; + + for (x=0; x < 5; x++) zmq_msg_init(&(msg[x])); + msgCnt = 0; + x = 0; + + // Get message + do { + // Get the message + if (zmq_recvmsg(data->zmqPull, &(msg[x]), ZMQ_DONTWAIT) > 0) { + if ( x != 4 ) x++; + msgCnt++; + + // Is there more data? + more = 0; + moreSize = 8; + zmq_getsockopt(data->zmqPull, ZMQ_RCVMORE, &more, &moreSize); + } else { + more = 0; + } + } while ( more ); + + // Proper message received + if (msgCnt == 4 || msgCnt == 5) { + // Check sizes + if ( (zmq_msg_size(&(msg[0])) != 4) || (zmq_msg_size(&(msg[1])) != 8) || + (zmq_msg_size(&(msg[2])) != 4) || (zmq_msg_size(&(msg[3])) != 4) ) { + vhpi_assert("RogueTcpMemory: Bad message size", vhpiFatal); for (x=0; x < msgCnt; x++) zmq_msg_close(&(msg[x])); return 0; - } - } + } + + // Get fields + memcpy(&(data->id), zmq_msg_data(&(msg[0])), 4); + memcpy(&(data->addr), zmq_msg_data(&(msg[1])), 8); + memcpy(&(data->size), zmq_msg_data(&(msg[2])), 4); + memcpy(&(data->type), zmq_msg_data(&(msg[3])), 4); + + // Write data is expected + if ( (data->type == T_WRITE) || (data->type == T_POST) ) { + if ( (msgCnt != 5) || (zmq_msg_size(&(msg[4])) != data->size) ) { + vhpi_assert("RogueTcpMemory: Transaction write data error", vhpiFatal); + for (x=0; x < msgCnt; x++) zmq_msg_close(&(msg[x])); + return 0; + } + } - // Data pointer - memcpy(data->data, zmq_msg_data(&(msg[4])), data->size); - data->state = ST_START; - data->curr = 0; - data->result = 0; + // Data pointer + memcpy(data->data, zmq_msg_data(&(msg[4])), data->size); + data->state = ST_START; + data->curr = 0; + data->result = 0; - vhpi_printf("%lu RogueTcpMemory: Got Tran: Id %i, Addr 0x%x, Size %i, Type %i\n", portData->simTime, data->id, data->addr, data->size, data->type); + vhpi_printf("%lu RogueTcpMemory: Got Tran: Id %i, Addr 0x%x, Size %i, Type %i\n", portData->simTime, data->id, data->addr, data->size, data->type); - return(data->size); - } - return (0); + return(data->size); + } + return (0); } // Init function void RogueTcpMemoryInit(vhpiHandleT compInst) { - // Create new port data structure - portDataT *portData = (portDataT *) malloc(sizeof(portDataT)); - RogueTcpMemoryData *data = (RogueTcpMemoryData *) malloc(sizeof(RogueTcpMemoryData)); - - // Get port count - portData->portCount = PORT_COUNT; - - // Set port directions - portData->portDir[s_clock] = vhpiIn; - portData->portDir[s_reset] = vhpiIn; - portData->portDir[s_port] = vhpiIn; - - portData->portDir[s_araddr] = vhpiOut; - portData->portDir[s_arprot] = vhpiOut; - portData->portDir[s_arvalid] = vhpiOut; - portData->portDir[s_rready] = vhpiOut; - - portData->portDir[s_arready] = vhpiIn; - portData->portDir[s_rdata] = vhpiIn; - portData->portDir[s_rresp] = vhpiIn; - portData->portDir[s_rvalid] = vhpiIn; - - portData->portDir[s_awaddr] = vhpiOut; - portData->portDir[s_awprot] = vhpiOut; - portData->portDir[s_awvalid] = vhpiOut; - portData->portDir[s_wdata] = vhpiOut; - portData->portDir[s_wstrb] = vhpiOut; - portData->portDir[s_wvalid] = vhpiOut; - portData->portDir[s_bready] = vhpiOut; - - portData->portDir[s_awready] = vhpiIn; - portData->portDir[s_wready] = vhpiIn; - portData->portDir[s_bresp] = vhpiIn; - portData->portDir[s_bvalid] = vhpiIn; - - // Set port widths - portData->portWidth[s_clock] = 1; - portData->portWidth[s_reset] = 1; - portData->portWidth[s_port] = 16; - - portData->portWidth[s_araddr] = 32; - portData->portWidth[s_arprot] = 3; - portData->portWidth[s_arvalid] = 1; - portData->portWidth[s_rready] = 1; - - portData->portWidth[s_arready] = 1; - portData->portWidth[s_rdata] = 32; - portData->portWidth[s_rresp] = 2; - portData->portWidth[s_rvalid] = 1; - - portData->portWidth[s_awaddr] = 32; - portData->portWidth[s_awprot] = 3; - portData->portWidth[s_awvalid] = 1; - portData->portWidth[s_wdata] = 32; - portData->portWidth[s_wstrb] = 4; - portData->portWidth[s_wvalid] = 1; - portData->portWidth[s_bready] = 1; - - portData->portWidth[s_awready] = 1; - portData->portWidth[s_wready] = 1; - portData->portWidth[s_bresp] = 2; - portData->portWidth[s_bvalid] = 1; - - // Create data structure to hold state - portData->stateData = data; - - // State update function - portData->stateUpdate = *RogueTcpMemoryUpdate; - - // Init - memset(data, 0, sizeof(RogueTcpMemoryData)); - - // Call generic Init - VhpiGenericInit(compInst, portData); + // Create new port data structure + portDataT *portData = (portDataT *) malloc(sizeof(portDataT)); + RogueTcpMemoryData *data = (RogueTcpMemoryData *) malloc(sizeof(RogueTcpMemoryData)); + + // Get port count + portData->portCount = PORT_COUNT; + + // Set port directions + portData->portDir[s_clock] = vhpiIn; + portData->portDir[s_reset] = vhpiIn; + portData->portDir[s_port] = vhpiIn; + + portData->portDir[s_araddr] = vhpiOut; + portData->portDir[s_arprot] = vhpiOut; + portData->portDir[s_arvalid] = vhpiOut; + portData->portDir[s_rready] = vhpiOut; + + portData->portDir[s_arready] = vhpiIn; + portData->portDir[s_rdata] = vhpiIn; + portData->portDir[s_rresp] = vhpiIn; + portData->portDir[s_rvalid] = vhpiIn; + + portData->portDir[s_awaddr] = vhpiOut; + portData->portDir[s_awprot] = vhpiOut; + portData->portDir[s_awvalid] = vhpiOut; + portData->portDir[s_wdata] = vhpiOut; + portData->portDir[s_wstrb] = vhpiOut; + portData->portDir[s_wvalid] = vhpiOut; + portData->portDir[s_bready] = vhpiOut; + + portData->portDir[s_awready] = vhpiIn; + portData->portDir[s_wready] = vhpiIn; + portData->portDir[s_bresp] = vhpiIn; + portData->portDir[s_bvalid] = vhpiIn; + + // Set port widths + portData->portWidth[s_clock] = 1; + portData->portWidth[s_reset] = 1; + portData->portWidth[s_port] = 16; + + portData->portWidth[s_araddr] = 32; + portData->portWidth[s_arprot] = 3; + portData->portWidth[s_arvalid] = 1; + portData->portWidth[s_rready] = 1; + + portData->portWidth[s_arready] = 1; + portData->portWidth[s_rdata] = 32; + portData->portWidth[s_rresp] = 2; + portData->portWidth[s_rvalid] = 1; + + portData->portWidth[s_awaddr] = 32; + portData->portWidth[s_awprot] = 3; + portData->portWidth[s_awvalid] = 1; + portData->portWidth[s_wdata] = 32; + portData->portWidth[s_wstrb] = 4; + portData->portWidth[s_wvalid] = 1; + portData->portWidth[s_bready] = 1; + + portData->portWidth[s_awready] = 1; + portData->portWidth[s_wready] = 1; + portData->portWidth[s_bresp] = 2; + portData->portWidth[s_bvalid] = 1; + + // Create data structure to hold state + portData->stateData = data; + + // State update function + portData->stateUpdate = *RogueTcpMemoryUpdate; + + // Init + memset(data, 0, sizeof(RogueTcpMemoryData)); + + // Call generic Init + VhpiGenericInit(compInst, portData); } // User function to update state based upon a signal change void RogueTcpMemoryUpdate(void *userPtr) { - uint32_t data32; - - portDataT *portData = (portDataT*) userPtr; - RogueTcpMemoryData *data = (RogueTcpMemoryData*)(portData->stateData); - - // Detect clock edge - if ( data->currClk != getInt(s_clock) ) { - data->currClk = getInt(s_clock); - - // Rising edge - if ( data->currClk ) { - // Reset is asserted - if ( getInt(s_reset) == 1 ) { - data->state = ST_IDLE; - setInt(s_arvalid, 0); - setInt(s_rready, 1); - setInt(s_awvalid, 0); - setInt(s_bready, 1); - - // Data movement - } else { - // Port not yet assigned - if ( data->port == 0 ) { - data->port = getInt(s_port); - RogueTcpMemoryRestart(data, portData); - } - - switch (data->state) { - // Idle get new data - case ST_IDLE: - RogueTcpMemoryRecv(data, portData); - break; - - // Start, present transaction - case ST_START: - - // Write - if ( data->type == T_WRITE || data->type == T_POST ) { - setInt(s_awaddr, (data->addr+data->curr)); - setInt(s_awprot, 0); - setInt(s_awvalid, 1); - setInt(s_bready, 1); - - data32 = data->data[data->curr++] & 0x000000FF; - data32 |= (data->data[data->curr++] << 8) & 0x0000FF00; - data32 |= (data->data[data->curr++] << 16) & 0x00FF0000; - data32 |= (data->data[data->curr++] << 24) & 0xFF000000; - - setInt(s_wdata, data32); - setInt(s_wstrb, 0xF); - setInt(s_wvalid, 1); - data->state = ST_WRESP; - - // Read - } else { - setInt(s_araddr, (data->addr+data->curr)); - setInt(s_arprot, 0); - setInt(s_arvalid, 1); - setInt(s_rready, 1); - data->state = ST_RADDR; - } - break; - - // Write response - case ST_WRESP: - - if ( getInt(s_awready) ) setInt(s_awvalid, 0); - if ( getInt(s_wready) ) setInt(s_wvalid, 0); - - if ( getInt(s_bvalid) ) { - // setInt(s_bready,0); - data->result = getInt(s_bresp); - - if (data->curr == data->size) { - RogueTcpMemorySend(data, portData); // state goes to idle - } else { - data->state = ST_PAUSE; - } - } - break; - - // Read address - case ST_RADDR: - if ( getInt(s_arready) ) { - setInt(s_arvalid, 0); - setInt(s_rready, 1); - data->state = ST_RDATA; - } - break; - - // Read data - case ST_RDATA: - if ( getInt(s_rvalid) ) { - data32 = getInt(s_rdata); - data->result = getInt(s_rresp); - - data->data[data->curr++] = data32 & 0xFF; - data->data[data->curr++] = (data32 >> 8) & 0xFF; - data->data[data->curr++] = (data32 >> 16) & 0xFF; - data->data[data->curr++] = (data32 >> 24) & 0xFF; - - // setInt(s_rready,0); - - if (data->curr == data->size) { - RogueTcpMemorySend(data, portData); // state goes to idle - } else { - data->state = ST_PAUSE; - } - } - break; - - // Wait for RVALID and BVALID to fall - case ST_PAUSE: - if ( getInt(s_rvalid) == 0 && getInt(s_bvalid) == 0 ) { - data->state = ST_START; - break; - } + uint32_t data32; + + portDataT *portData = (portDataT*) userPtr; + RogueTcpMemoryData *data = (RogueTcpMemoryData*)(portData->stateData); + + // Detect clock edge + if ( data->currClk != getInt(s_clock) ) { + data->currClk = getInt(s_clock); + + // Rising edge + if ( data->currClk ) { + // Reset is asserted + if ( getInt(s_reset) == 1 ) { + data->state = ST_IDLE; + setInt(s_arvalid, 0); + setInt(s_rready, 1); + setInt(s_awvalid, 0); + setInt(s_bready, 1); + + // Data movement + } else { + // Port not yet assigned + if ( data->port == 0 ) { + data->port = getInt(s_port); + RogueTcpMemoryRestart(data, portData); + } + + switch (data->state) { + // Idle get new data + case ST_IDLE: + RogueTcpMemoryRecv(data, portData); + break; + + // Start, present transaction + case ST_START: + + // Write + if ( data->type == T_WRITE || data->type == T_POST ) { + setInt(s_awaddr, (data->addr+data->curr)); + setInt(s_awprot, 0); + setInt(s_awvalid, 1); + setInt(s_bready, 1); + + data32 = data->data[data->curr++] & 0x000000FF; + data32 |= (data->data[data->curr++] << 8) & 0x0000FF00; + data32 |= (data->data[data->curr++] << 16) & 0x00FF0000; + data32 |= (data->data[data->curr++] << 24) & 0xFF000000; + + setInt(s_wdata, data32); + setInt(s_wstrb, 0xF); + setInt(s_wvalid, 1); + data->state = ST_WRESP; + + // Read + } else { + setInt(s_araddr, (data->addr+data->curr)); + setInt(s_arprot, 0); + setInt(s_arvalid, 1); + setInt(s_rready, 1); + data->state = ST_RADDR; + } + break; + + // Write response + case ST_WRESP: + + if ( getInt(s_awready) ) setInt(s_awvalid, 0); + if ( getInt(s_wready) ) setInt(s_wvalid, 0); + + if ( getInt(s_bvalid) ) { + // setInt(s_bready,0); + data->result = getInt(s_bresp); + + if (data->curr == data->size) { + RogueTcpMemorySend(data, portData); // state goes to idle + } else { + data->state = ST_PAUSE; + } + } + break; + + // Read address + case ST_RADDR: + if ( getInt(s_arready) ) { + setInt(s_arvalid, 0); + setInt(s_rready, 1); + data->state = ST_RDATA; + } + break; + + // Read data + case ST_RDATA: + if ( getInt(s_rvalid) ) { + data32 = getInt(s_rdata); + data->result = getInt(s_rresp); + + data->data[data->curr++] = data32 & 0xFF; + data->data[data->curr++] = (data32 >> 8) & 0xFF; + data->data[data->curr++] = (data32 >> 16) & 0xFF; + data->data[data->curr++] = (data32 >> 24) & 0xFF; + + // setInt(s_rready,0); + + if (data->curr == data->size) { + RogueTcpMemorySend(data, portData); // state goes to idle + } else { + data->state = ST_PAUSE; + } + } + break; + + // Wait for RVALID and BVALID to fall + case ST_PAUSE: + if ( getInt(s_rvalid) == 0 && getInt(s_bvalid) == 0 ) { + data->state = ST_START; + break; + } + } } - } - } - } + } + } } diff --git a/axi/simlink/src/RogueTcpStream.c b/axi/simlink/src/RogueTcpStream.c index c03715b3d2..960bff89bb 100755 --- a/axi/simlink/src/RogueTcpStream.c +++ b/axi/simlink/src/RogueTcpStream.c @@ -26,358 +26,357 @@ // Start/resetart zeromq server void RogueTcpStreamRestart(RogueTcpStreamData *data, portDataT *portData) { - char buffer[100]; + char buffer[100]; - if ( data->zmqPush != NULL ) zmq_close(data->zmqPush ); - if ( data->zmqPull != NULL ) zmq_close(data->zmqPull ); - if ( data->zmqCtx != NULL ) zmq_term(data->zmqCtx); + if ( data->zmqPush != NULL ) zmq_close(data->zmqPush ); + if ( data->zmqPull != NULL ) zmq_close(data->zmqPull ); + if ( data->zmqCtx != NULL ) zmq_term(data->zmqCtx); - data->zmqCtx = NULL; - data->zmqPush = NULL; - data->zmqPull = NULL; + data->zmqCtx = NULL; + data->zmqPush = NULL; + data->zmqPull = NULL; - data->zmqCtx = zmq_ctx_new(); - data->zmqPull = zmq_socket(data->zmqCtx, ZMQ_PULL); - data->zmqPush = zmq_socket(data->zmqCtx, ZMQ_PUSH); + data->zmqCtx = zmq_ctx_new(); + data->zmqPull = zmq_socket(data->zmqCtx, ZMQ_PULL); + data->zmqPush = zmq_socket(data->zmqCtx, ZMQ_PUSH); - vhpi_printf("RogueTcpStream: Listening on ports %i & %i\n", data->port, data->port+1); + vhpi_printf("RogueTcpStream: Listening on ports %i & %i\n", data->port, data->port+1); - snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port); - if ( zmq_bind(data->zmqPull, buffer) ) { - vhpi_assert("RogueTcpStream: Failed to bind pull port", vhpiFatal); - return; - } + snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port); + if ( zmq_bind(data->zmqPull, buffer) ) { + vhpi_assert("RogueTcpStream: Failed to bind pull port", vhpiFatal); + return; + } - snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port+1); - if ( zmq_bind(data->zmqPush, buffer) ) { - vhpi_assert("RogueTcpStream: Failed to bind push port", vhpiFatal); - return; - } + snprintf(buffer, sizeof(buffer), "tcp://127.0.0.1:%i", data->port+1); + if ( zmq_bind(data->zmqPush, buffer) ) { + vhpi_assert("RogueTcpStream: Failed to bind push port", vhpiFatal); + return; + } } // Send a message void RogueTcpStreamSend(RogueTcpStreamData *data, portDataT *portData) { - zmq_msg_t msg[4]; - uint16_t flags; - uint8_t chan; - uint8_t err; - uint32_t x; - int error; - - if ( (zmq_msg_init_size(&(msg[0]), 2) < 0) || // Flags - (zmq_msg_init_size(&(msg[1]), 1) < 0) || // Channel - (zmq_msg_init_size(&(msg[2]), 1) < 0) ) { // Error - vhpi_assert("RogueTcpStream: Failed to init message header", vhpiFatal); - return; - } - - if (zmq_msg_init_size(&(msg[3]), data->ibSize) < 0) { - vhpi_assert("RogueTcpStream: Failed to init message", vhpiFatal); - return; - } - - if ( data->ssi ) { - flags = (data->ibFuser & 0xFF); - flags |= ((data->ibLuser << 8) & 0xFF00); - err = data->ibLuser & 0x1; - } else { - flags = 0; - err = 0; - } - chan = 0; - - memcpy(zmq_msg_data(&(msg[0])), &flags, 2); - memcpy(zmq_msg_data(&(msg[1])), &chan, 1); - memcpy(zmq_msg_data(&(msg[2])), &err, 1); - - // Copy data - memcpy(zmq_msg_data(&(msg[3])), data->ibData, data->ibSize); - - // Send data - for (x=0; x < 4; x++) { - if ( zmq_msg_send(&(msg[x]), data->zmqPush, (x == 3)?0:ZMQ_SNDMORE) < 0 ) { - error = errno; - vhpi_printf("Failed to send message on port %i - x: %i - err: %i\n", data->port+1, x, error); - vhpi_printf("Error: %s\n", strerror(error)); - vhpi_assert("RogueTcpStream: Failed to send message", vhpiFatal); - } - } - vhpi_printf("%lu RogueTcpStream: Send data: Size: %i, flags: %x, chan: %x, err: %x, port: %i\n", portData->simTime, data->ibSize, flags, chan, err, data->port+1); - data->ibSize = 0; + zmq_msg_t msg[4]; + uint16_t flags; + uint8_t chan; + uint8_t err; + uint32_t x; + int error; + + if ( (zmq_msg_init_size(&(msg[0]), 2) < 0) || // Flags + (zmq_msg_init_size(&(msg[1]), 1) < 0) || // Channel + (zmq_msg_init_size(&(msg[2]), 1) < 0) ) { // Error + vhpi_assert("RogueTcpStream: Failed to init message header", vhpiFatal); + return; + } + + if (zmq_msg_init_size(&(msg[3]), data->ibSize) < 0) { + vhpi_assert("RogueTcpStream: Failed to init message", vhpiFatal); + return; + } + + if ( data->ssi ) { + flags = (data->ibFuser & 0xFF); + flags |= ((data->ibLuser << 8) & 0xFF00); + err = data->ibLuser & 0x1; + } else { + flags = 0; + err = 0; + } + chan = 0; + + memcpy(zmq_msg_data(&(msg[0])), &flags, 2); + memcpy(zmq_msg_data(&(msg[1])), &chan, 1); + memcpy(zmq_msg_data(&(msg[2])), &err, 1); + + // Copy data + memcpy(zmq_msg_data(&(msg[3])), data->ibData, data->ibSize); + + // Send data + for (x=0; x < 4; x++) { + if ( zmq_msg_send(&(msg[x]), data->zmqPush, (x == 3)?0:ZMQ_SNDMORE) < 0 ) { + error = errno; + vhpi_printf("Failed to send message on port %i - x: %i - err: %i\n", data->port+1, x, error); + vhpi_printf("Error: %s\n", strerror(error)); + vhpi_assert("RogueTcpStream: Failed to send message", vhpiFatal); + } + } + vhpi_printf("%lu RogueTcpStream: Send data: Size: %i, flags: %x, chan: %x, err: %x, port: %i\n", portData->simTime, data->ibSize, flags, chan, err, data->port+1); + data->ibSize = 0; } // Receive data if it is available int RogueTcpStreamRecv(RogueTcpStreamData *data, portDataT *portData) { - int64_t more; - size_t moreSize; - uint32_t size; - zmq_msg_t msg[4]; - uint32_t msgCnt; - uint16_t flags; - uint8_t chan; - uint8_t err; - uint32_t x; - - for (x=0; x < 4; x++) zmq_msg_init(&(msg[x])); - msgCnt = 0; - x = 0; - - // Get message - do { - // Get the message - if ( zmq_recvmsg(data->zmqPull, &(msg[x]), ZMQ_DONTWAIT) > 0 ) { - if ( x != 3 ) x++; - msgCnt++; - - // Is there more data? - more = 0; - moreSize = 8; - zmq_getsockopt(data->zmqPull, ZMQ_RCVMORE, &more, &moreSize); - } else { - more = 0; - } - } while ( more ); - - // Proper message received - if ( msgCnt == 4 ) { - // Check sizes - if ( (zmq_msg_size(&(msg[0])) != 2) || (zmq_msg_size(&(msg[1])) != 1) || - (zmq_msg_size(&(msg[2])) != 1) ) { - vhpi_assert("RogueTcpStream: Bad message sizes", vhpiFatal); - for (x=0; x < msgCnt; x++) zmq_msg_close(&(msg[x])); - return 0; - } - - // Get fields - memcpy(&flags, zmq_msg_data(&(msg[0])), 2); - memcpy(&chan, zmq_msg_data(&(msg[1])), 1); - memcpy(&err, zmq_msg_data(&(msg[2])), 1); - - // Get message info - size = zmq_msg_size(&(msg[3])); - - // Set data - memcpy(data->obData, zmq_msg_data(&(msg[3])), size); - data->obSize = size; - data->obFuser = flags & 0xFF; - data->obLuser = (flags >> 8) & 0xFF; - - if ( data->ssi ) { - data->obFuser |= 0x02; - if ( err ) data->obLuser |= 0x01; - } - - vhpi_printf("%lu RogueTcpStream: Recv data: Size: %i, flags: %x, chan: %i, err: %i, port: %i\n", portData->simTime, data->obSize, flags, chan, err, data->port); - - } else { - size = 0; - } - - for (x=0; x < 4; x++) zmq_msg_close(&(msg[x])); - - return(size); + int64_t more; + size_t moreSize; + uint32_t size; + zmq_msg_t msg[4]; + uint32_t msgCnt; + uint16_t flags; + uint8_t chan; + uint8_t err; + uint32_t x; + + for (x=0; x < 4; x++) zmq_msg_init(&(msg[x])); + msgCnt = 0; + x = 0; + + // Get message + do { + // Get the message + if ( zmq_recvmsg(data->zmqPull, &(msg[x]), ZMQ_DONTWAIT) > 0 ) { + if ( x != 3 ) x++; + msgCnt++; + + // Is there more data? + more = 0; + moreSize = 8; + zmq_getsockopt(data->zmqPull, ZMQ_RCVMORE, &more, &moreSize); + } else { + more = 0; + } + } while ( more ); + + // Proper message received + if ( msgCnt == 4 ) { + // Check sizes + if ( (zmq_msg_size(&(msg[0])) != 2) || (zmq_msg_size(&(msg[1])) != 1) || (zmq_msg_size(&(msg[2])) != 1) ) { + vhpi_assert("RogueTcpStream: Bad message sizes", vhpiFatal); + for (x=0; x < msgCnt; x++) zmq_msg_close(&(msg[x])); + return 0; + } + + // Get fields + memcpy(&flags, zmq_msg_data(&(msg[0])), 2); + memcpy(&chan, zmq_msg_data(&(msg[1])), 1); + memcpy(&err, zmq_msg_data(&(msg[2])), 1); + + // Get message info + size = zmq_msg_size(&(msg[3])); + + // Set data + memcpy(data->obData, zmq_msg_data(&(msg[3])), size); + data->obSize = size; + data->obFuser = flags & 0xFF; + data->obLuser = (flags >> 8) & 0xFF; + + if ( data->ssi ) { + data->obFuser |= 0x02; + if ( err ) data->obLuser |= 0x01; + } + + vhpi_printf("%lu RogueTcpStream: Recv data: Size: %i, flags: %x, chan: %i, err: %i, port: %i\n", portData->simTime, data->obSize, flags, chan, err, data->port); + + } else { + size = 0; + } + + for (x=0; x < 4; x++) zmq_msg_close(&(msg[x])); + + return(size); } // Init function void RogueTcpStreamInit(vhpiHandleT compInst) { - // Create new port data structure - portDataT *portData = (portDataT *) malloc(sizeof(portDataT)); - RogueTcpStreamData *data = (RogueTcpStreamData *) malloc(sizeof(RogueTcpStreamData)); - - // Get port count - portData->portCount = PORT_COUNT; - - // Set port directions - portData->portDir[s_clock] = vhpiIn; - portData->portDir[s_reset] = vhpiIn; - portData->portDir[s_port] = vhpiIn; - portData->portDir[s_ssi] = vhpiIn; - - portData->portDir[s_obValid] = vhpiOut; - portData->portDir[s_obReady] = vhpiIn; - portData->portDir[s_obDataLow] = vhpiOut; - portData->portDir[s_obDataHigh] = vhpiOut; - portData->portDir[s_obUserLow] = vhpiOut; - portData->portDir[s_obUserHigh] = vhpiOut; - portData->portDir[s_obKeep] = vhpiOut; - portData->portDir[s_obLast] = vhpiOut; - - portData->portDir[s_ibValid] = vhpiIn; - portData->portDir[s_ibReady] = vhpiOut; - portData->portDir[s_ibDataLow] = vhpiIn; - portData->portDir[s_ibDataHigh] = vhpiIn; - portData->portDir[s_ibUserLow] = vhpiIn; - portData->portDir[s_ibUserHigh] = vhpiIn; - portData->portDir[s_ibKeep] = vhpiIn; - portData->portDir[s_ibLast] = vhpiIn; - - // Set port widths - portData->portWidth[s_clock] = 1; - portData->portWidth[s_reset] = 1; - portData->portWidth[s_port] = 16; - portData->portWidth[s_ssi] = 1; - - portData->portWidth[s_obValid] = 1; - portData->portWidth[s_obReady] = 1; - portData->portWidth[s_obDataLow] = 32; - portData->portWidth[s_obDataHigh] = 32; - portData->portWidth[s_obUserLow] = 32; - portData->portWidth[s_obUserHigh] = 32; - portData->portWidth[s_obKeep] = 8; - portData->portWidth[s_obLast] = 1; - - portData->portWidth[s_ibValid] = 1; - portData->portWidth[s_ibReady] = 1; - portData->portWidth[s_ibDataLow] = 32; - portData->portWidth[s_ibDataHigh] = 32; - portData->portWidth[s_ibUserLow] = 32; - portData->portWidth[s_ibUserHigh] = 32; - portData->portWidth[s_ibKeep] = 8; - portData->portWidth[s_ibLast] = 1; - - // Create data structure to hold state - portData->stateData = data; - - // State update function - portData->stateUpdate = *RogueTcpStreamUpdate; - - // Init - memset(data, 0, sizeof(RogueTcpStreamData)); - time(&(data->ltime)); - - // Call generic Init - VhpiGenericInit(compInst, portData); + // Create new port data structure + portDataT *portData = (portDataT *) malloc(sizeof(portDataT)); + RogueTcpStreamData *data = (RogueTcpStreamData *) malloc(sizeof(RogueTcpStreamData)); + + // Get port count + portData->portCount = PORT_COUNT; + + // Set port directions + portData->portDir[s_clock] = vhpiIn; + portData->portDir[s_reset] = vhpiIn; + portData->portDir[s_port] = vhpiIn; + portData->portDir[s_ssi] = vhpiIn; + + portData->portDir[s_obValid] = vhpiOut; + portData->portDir[s_obReady] = vhpiIn; + portData->portDir[s_obDataLow] = vhpiOut; + portData->portDir[s_obDataHigh] = vhpiOut; + portData->portDir[s_obUserLow] = vhpiOut; + portData->portDir[s_obUserHigh] = vhpiOut; + portData->portDir[s_obKeep] = vhpiOut; + portData->portDir[s_obLast] = vhpiOut; + + portData->portDir[s_ibValid] = vhpiIn; + portData->portDir[s_ibReady] = vhpiOut; + portData->portDir[s_ibDataLow] = vhpiIn; + portData->portDir[s_ibDataHigh] = vhpiIn; + portData->portDir[s_ibUserLow] = vhpiIn; + portData->portDir[s_ibUserHigh] = vhpiIn; + portData->portDir[s_ibKeep] = vhpiIn; + portData->portDir[s_ibLast] = vhpiIn; + + // Set port widths + portData->portWidth[s_clock] = 1; + portData->portWidth[s_reset] = 1; + portData->portWidth[s_port] = 16; + portData->portWidth[s_ssi] = 1; + + portData->portWidth[s_obValid] = 1; + portData->portWidth[s_obReady] = 1; + portData->portWidth[s_obDataLow] = 32; + portData->portWidth[s_obDataHigh] = 32; + portData->portWidth[s_obUserLow] = 32; + portData->portWidth[s_obUserHigh] = 32; + portData->portWidth[s_obKeep] = 8; + portData->portWidth[s_obLast] = 1; + + portData->portWidth[s_ibValid] = 1; + portData->portWidth[s_ibReady] = 1; + portData->portWidth[s_ibDataLow] = 32; + portData->portWidth[s_ibDataHigh] = 32; + portData->portWidth[s_ibUserLow] = 32; + portData->portWidth[s_ibUserHigh] = 32; + portData->portWidth[s_ibKeep] = 8; + portData->portWidth[s_ibLast] = 1; + + // Create data structure to hold state + portData->stateData = data; + + // State update function + portData->stateUpdate = *RogueTcpStreamUpdate; + + // Init + memset(data, 0, sizeof(RogueTcpStreamData)); + time(&(data->ltime)); + + // Call generic Init + VhpiGenericInit(compInst, portData); } // User function to update state based upon a signal change void RogueTcpStreamUpdate(void *userPtr) { - uint32_t x; - uint32_t keep; - uint32_t dLow; - uint32_t dHigh; - uint32_t uLow; - uint32_t uHigh; - - portDataT *portData = (portDataT*) userPtr; - RogueTcpStreamData *data = (RogueTcpStreamData*)(portData->stateData); - - // Detect clock edge - if ( data->currClk != getInt(s_clock) ) { - data->currClk = getInt(s_clock); - - // Rising edge - if ( data->currClk ) { - // Reset is asserted - if ( getInt(s_reset) == 1 ) { - data->obCount = 0; - data->obSize = 0; - data->ibSize = 0; - data->obValid = 0; - setInt(s_obValid, 0); - setInt(s_ibReady, 1); - setInt(s_obDataLow, 0); - setInt(s_obDataHigh, 0); - setInt(s_obUserLow, 0); - setInt(s_obUserHigh, 0); - setInt(s_obKeep, 0); - setInt(s_obLast, 0); - - // Data movement - } else { - // Port not yet assigned - if ( data->port == 0 ) { - data->port = getInt(s_port); - data->ssi = getInt(s_ssi); - RogueTcpStreamRestart(data, portData); + uint32_t x; + uint32_t keep; + uint32_t dLow; + uint32_t dHigh; + uint32_t uLow; + uint32_t uHigh; + + portDataT *portData = (portDataT*) userPtr; + RogueTcpStreamData *data = (RogueTcpStreamData*)(portData->stateData); + + // Detect clock edge + if ( data->currClk != getInt(s_clock) ) { + data->currClk = getInt(s_clock); + + // Rising edge + if ( data->currClk ) { + // Reset is asserted + if ( getInt(s_reset) == 1 ) { + data->obCount = 0; + data->obSize = 0; + data->ibSize = 0; + data->obValid = 0; + setInt(s_obValid, 0); + setInt(s_ibReady, 1); + setInt(s_obDataLow, 0); + setInt(s_obDataHigh, 0); + setInt(s_obUserLow, 0); + setInt(s_obUserHigh, 0); + setInt(s_obKeep, 0); + setInt(s_obLast, 0); + + // Data movement + } else { + // Port not yet assigned + if ( data->port == 0 ) { + data->port = getInt(s_port); + data->ssi = getInt(s_ssi); + RogueTcpStreamRestart(data, portData); + } + + // Inbound + if (getInt(s_ibValid)) { + keep = getInt(s_ibKeep); + dLow = getInt(s_ibDataLow); + dHigh = getInt(s_ibDataHigh); + uLow = getInt(s_ibUserLow); + uHigh = getInt(s_ibUserHigh); + + // First + if ( data->ibSize == 0 ) data->ibFuser = uLow & 0xFF; + + // Get data + for (x=0; x< 8; x++) { + if ( x < 4 ) { + data->ibData[data->ibSize] = (dLow >> (x*8)) & 0xFF; + if ( (keep >> x) && 1 ) data->ibLuser = (uLow >> (x*8)) & 0xFF; + } else { + data->ibData[data->ibSize] = (dHigh >> ((x-4)*8)) & 0xFF; + if ( (keep >> x) && 1 ) data->ibLuser = (uHigh >> ((x-4)*8)) & 0xFF; + } + if ( (keep >> x) && 1 ) data->ibSize++; + } + + // Last + if ( getInt(s_ibLast) ) RogueTcpStreamSend(data, portData); + } + + // Not in frame + if ( data->obSize == 0 ) RogueTcpStreamRecv(data, portData); + + // Data accepted + if ( getInt(s_obReady) ) { + data->obValid = 0; + setInt(s_obLast, 0); + } + + // Valid not asserted and data is ready + if ( data->obValid == 0 && data->obSize > 0 ) { + // First user + if ( data->obCount == 0 ) { + setInt(s_obUserLow, data->obFuser); + } else { + setInt(s_obUserLow, 0); + } + setInt(s_obUserHigh, 0); + + // Get data + dHigh = 0; + dLow = 0; + keep = 0; + + // Set data + for (x=0; x< 8; x++) { + if ( x < 4 ) { + dLow |= (data->obData[data->obCount] << (x*8)); + if ( (data->obCount+1) == data->obSize ) { + if (data->obCount < 4) { + setInt(s_obUserLow, (data->obLuser << (x*8))|(data->obFuser)); + } else { + setInt(s_obUserLow, (data->obLuser << (x*8))); + } + } + } else { + dHigh |= (data->obData[data->obCount] << ((x-4)*8)); + if ( (data->obCount+1) == data->obSize ) + setInt(s_obUserHigh, (data->obLuser << ((x-4)*8))); + } + + data->obCount++; + if ( data->obCount <= data->obSize ) keep |= (1 << x); + } + setInt(s_obDataLow, dLow); + setInt(s_obDataHigh, dHigh); + setInt(s_obKeep, keep); + data->obValid = 1; + + // Done + if ( data->obCount >= data->obSize ) { + setInt(s_obLast, 1); + data->obSize = 0; + data->obCount = 0; + } + } + + // Output valid + setInt(s_obValid, data->obValid); } - - // Inbound - if (getInt(s_ibValid)) { - keep = getInt(s_ibKeep); - dLow = getInt(s_ibDataLow); - dHigh = getInt(s_ibDataHigh); - uLow = getInt(s_ibUserLow); - uHigh = getInt(s_ibUserHigh); - - // First - if ( data->ibSize == 0 ) data->ibFuser = uLow & 0xFF; - - // Get data - for (x=0; x< 8; x++) { - if ( x < 4 ) { - data->ibData[data->ibSize] = (dLow >> (x*8)) & 0xFF; - if ( (keep >> x) && 1 ) data->ibLuser = (uLow >> (x*8)) & 0xFF; - } else { - data->ibData[data->ibSize] = (dHigh >> ((x-4)*8)) & 0xFF; - if ( (keep >> x) && 1 ) data->ibLuser = (uHigh >> ((x-4)*8)) & 0xFF; - } - if ( (keep >> x) && 1 ) data->ibSize++; - } - - // Last - if ( getInt(s_ibLast) ) RogueTcpStreamSend(data, portData); - } - - // Not in frame - if ( data->obSize == 0 ) RogueTcpStreamRecv(data, portData); - - // Data accepted - if ( getInt(s_obReady) ) { - data->obValid = 0; - setInt(s_obLast, 0); - } - - // Valid not asserted and data is ready - if ( data->obValid == 0 && data->obSize > 0 ) { - // First user - if ( data->obCount == 0 ) { - setInt(s_obUserLow, data->obFuser); - } else { - setInt(s_obUserLow, 0); - } - setInt(s_obUserHigh, 0); - - // Get data - dHigh = 0; - dLow = 0; - keep = 0; - - // Set data - for (x=0; x< 8; x++) { - if ( x < 4 ) { - dLow |= (data->obData[data->obCount] << (x*8)); - if ( (data->obCount+1) == data->obSize ) { - if (data->obCount < 4) { - setInt(s_obUserLow, (data->obLuser << (x*8))|(data->obFuser)); - } else { - setInt(s_obUserLow, (data->obLuser << (x*8))); - } - } - } else { - dHigh |= (data->obData[data->obCount] << ((x-4)*8)); - if ( (data->obCount+1) == data->obSize ) - setInt(s_obUserHigh, (data->obLuser << ((x-4)*8))); - } - - data->obCount++; - if ( data->obCount <= data->obSize ) keep |= (1 << x); - } - setInt(s_obDataLow, dLow); - setInt(s_obDataHigh, dHigh); - setInt(s_obKeep, keep); - data->obValid = 1; - - // Done - if ( data->obCount >= data->obSize ) { - setInt(s_obLast, 1); - data->obSize = 0; - data->obCount = 0; - } - } - - // Output valid - setInt(s_obValid, data->obValid); - } - } - } + } + } } diff --git a/axi/simlink/src/VhpiGeneric.c b/axi/simlink/src/VhpiGeneric.c index 30523321f5..b0a227b294 100755 --- a/axi/simlink/src/VhpiGeneric.c +++ b/axi/simlink/src/VhpiGeneric.c @@ -29,199 +29,197 @@ // Convert input values from enum to int void VhpiGenericConvertIn(portDataT *portData) { - // Go through each port - int x, y, bit; - for (x=0; x < portData->portCount; x++) { - if ( portData->portDir[x] != vhpiOut ) { - if ( portData->portWidth[x] == 1 ) { - if ( portData->portValue[x]->value.enumval == 3 ) { - portData->intValue[x] = 1; + // Go through each port + int x, y, bit; + for (x=0; x < portData->portCount; x++) { + if ( portData->portDir[x] != vhpiOut ) { + if ( portData->portWidth[x] == 1 ) { + if ( portData->portValue[x]->value.enumval == 3 ) { + portData->intValue[x] = 1; + } else { + portData->intValue[x] = 0; + } } else { - portData->intValue[x] = 0; + portData->intValue[x] = 0; + for (y=0; y < portData->portWidth[x]; y++) { + bit = (portData->portWidth[x] - 1) - y; + if ( portData->portValue[x]->value.enums[y] == 3 ) { + portData->intValue[x] += 1 << bit; + } + } } - } else { - portData->intValue[x] = 0; - for (y=0; y < portData->portWidth[x]; y++) { - bit = (portData->portWidth[x] - 1) - y; - if ( portData->portValue[x]->value.enums[y] == 3 ) { - portData->intValue[x] += 1 << bit; - } - } - } - } - } + } + } } // Convert output values from int to enum void VhpiGenericConvertOut(portDataT *portData) { - // Go through each port - int x, y, bit, temp; - for (x=0; x < portData->portCount; x++) { - if ( portData->portDir[x] != vhpiIn ) { - if ( portData->portWidth[x] == 1 ) { - if ( portData->outEnable[x] == 1 ) { - if ( portData->intValue[x] == 0 ) { - portData->portValue[x]->value.enumval = 2; - } else { - portData->portValue[x]->value.enumval = 3; - } - } else { - portData->portValue[x]->value.enumval = 4; // Tri-state - } - } else { - if ( portData->outEnable[x] == 1 ) { - for (y=0; y < portData->portWidth[x]; y++) { - bit = (portData->portWidth[x] - 1) - y; - temp = 1 << bit; - if ( (portData->intValue[x] & temp) != 0 ) { - portData->portValue[x]->value.enums[y] = 3; - } else { - portData->portValue[x]->value.enums[y] = 2; - } - } + // Go through each port + int x, y, bit, temp; + for (x=0; x < portData->portCount; x++) { + if ( portData->portDir[x] != vhpiIn ) { + if ( portData->portWidth[x] == 1 ) { + if ( portData->outEnable[x] == 1 ) { + if ( portData->intValue[x] == 0 ) { + portData->portValue[x]->value.enumval = 2; + } else { + portData->portValue[x]->value.enumval = 3; + } + } else { + portData->portValue[x]->value.enumval = 4; // Tri-state + } } else { - for (y=0; y < portData->portWidth[x]; y++) { - portData->portValue[x]->value.enums[y] = 4; // Tri-state - } + if ( portData->outEnable[x] == 1 ) { + for (y=0; y < portData->portWidth[x]; y++) { + bit = (portData->portWidth[x] - 1) - y; + temp = 1 << bit; + if ( (portData->intValue[x] & temp) != 0 ) { + portData->portValue[x]->value.enums[y] = 3; + } else { + portData->portValue[x]->value.enums[y] = 2; + } + } + } else { + for (y=0; y < portData->portWidth[x]; y++) { + portData->portValue[x]->value.enums[y] = 4; // Tri-state + } + } } - } - } - } + } + } } // Function that is called when the inputs have changed state // Copy values over and call user function for further handling void VhpiGenericCallBack(vhpiCbDataT *cbData) { - int x; - int ret; - - // Get user data - portDataT *portData = (portDataT *)cbData->user_data; - - // Get current state of all ports - for (x=0; x < portData->portCount; x++) { - // Get the inital input values - if ( portData->portDir[x] != vhpiOut ) - if ( ( ret = vhpi_get_value(portData->portHandle[x], portData->portValue[x])) ) - vhpi_printf("vhpi_get_value status error %i for port %i\n", ret, x); - } - - // Convert Input values - VhpiGenericConvertIn(portData); - - // Get simulation time - vhpi_get_time(&(portData->simTime), NULL); - - // Call the user function to update state - portData->stateUpdate(portData); - - // Convert Output values - VhpiGenericConvertOut(portData); - - // Set output values - for (x=0; x < portData->portCount; x++) { - if ( portData->portDir[x] != vhpiIn ) - if ( (ret = vhpi_put_value(portData->portHandle[x], portData->portValue[x], vhpiForcePropagate))) - vhpi_printf("vhpi_put_value status error %i for port %i\n", ret, x); - } + int x; + int ret; + + // Get user data + portDataT *portData = (portDataT *)cbData->user_data; + + // Get current state of all ports + for (x=0; x < portData->portCount; x++) { + // Get the inital input values + if ( portData->portDir[x] != vhpiOut ) + if ( ( ret = vhpi_get_value(portData->portHandle[x], portData->portValue[x])) ) + vhpi_printf("vhpi_get_value status error %i for port %i\n", ret, x); + } + + // Convert Input values + VhpiGenericConvertIn(portData); + + // Get simulation time + vhpi_get_time(&(portData->simTime), NULL); + + // Call the user function to update state + portData->stateUpdate(portData); + + // Convert Output values + VhpiGenericConvertOut(portData); + + // Set output values + for (x=0; x < portData->portCount; x++) { + if ( portData->portDir[x] != vhpiIn ) + if ( (ret = vhpi_put_value(portData->portHandle[x], portData->portValue[x], vhpiForcePropagate))) + vhpi_printf("vhpi_put_value status error %i for port %i\n", ret, x); + } } // Error handling function void VhpiGenericErrors(vhpiCbDataT *cb) { - vhpiErrorInfoT g_error; - while (vhpi_chk_error(&g_error)) - vhpi_printf("\tError: %s: %s\n", g_error.str, g_error.message); + vhpiErrorInfoT g_error; + while (vhpi_chk_error(&g_error)) + vhpi_printf("\tError: %s: %s\n", g_error.str, g_error.message); } // Function that is called as the module is elaborated. // Here we will simply register an error handling callback function. void VhpiGenericElab(vhpiHandleT compInst) { - // Create callback structure, setup callback function - vhpiCbDataT* pCbData = (vhpiCbDataT*) malloc(sizeof(vhpiCbDataT)); - pCbData->cbf = VhpiGenericErrors; - pCbData->time = (vhpiTimeT*) malloc(sizeof(vhpiTimeT)); - pCbData->reason = vhpiCbPLIError; + // Create callback structure, setup callback function + vhpiCbDataT* pCbData = (vhpiCbDataT*) malloc(sizeof(vhpiCbDataT)); + pCbData->cbf = VhpiGenericErrors; + pCbData->time = (vhpiTimeT*) malloc(sizeof(vhpiTimeT)); + pCbData->reason = vhpiCbPLIError; #if (VCS_VERSION >= 2016) - vhpi_register_cb(pCbData, vhpiReturnCb); + vhpi_register_cb(pCbData, vhpiReturnCb); #else - vhpi_register_cb(pCbData); + vhpi_register_cb(pCbData); #endif } // Function that is called as the module is initialized. // Check ports and setup functions to handle clock changes void VhpiGenericInit(vhpiHandleT compInst, portDataT *portData) { - vhpiCbDataT *cbData; - int width; - int x, y; - char *temp; - - // Blank out port handles and create value structures - for (x=0; x < portData->portCount; x++) { - portData->portHandle[x] = 0; - portData->portValue[x] = (vhpiValueT *) malloc(sizeof(vhpiValueT)); - portData->intValue[x] = 0; - portData->outEnable[x] = 1; - - memset(portData->portValue[x], 0, sizeof(vhpiValueT)); - } - - // Copy block name - temp = vhpi_get_str(vhpiFullNameP, compInst); - portData->blockName = (char *) malloc(strlen(temp)+1); - strcpy(portData->blockName, temp);//NOLINT - - // Get each port and verify width and direction, get initial value - for (x=0; x < portData->portCount; x++) { - // Get ID - portData->portHandle[x] = vhpi_handle_by_index(vhpiPortDecls, compInst, x); - - // Setup value types - if ( portData->portWidth[x] == 1 ) { - portData->portValue[x]->format = vhpiEnumVal; - portData->portValue[x]->value.enumval = 2; - } else { - portData->portValue[x]->format = vhpiEnumVecVal; - width = vhpi_value_size(portData->portHandle[x], vhpiEnumVecVal); - portData->portValue[x]->value.enums = (vhpiEnumT*)malloc(width); - portData->portValue[x]->bufSize = width; - for (y=0; y < portData->portWidth[x]; y++ ) - portData->portValue[x]->value.enums[y] = 2; - } - - // Check direction - if (vhpi_get(vhpiModeP, portData->portHandle[x]) != portData->portDir[x]) - vhpi_printf("Error: Port '%s' direction mismatch\n", - vhpi_get_str(vhpiFullNameP, portData->portHandle[x])); - - // Check width - if (vhpi_get(vhpiSizeP, portData->portHandle[x]) != portData->portWidth[x]) - vhpi_printf("Error: Port '%s' size mismatch\n", - vhpi_get_str(vhpiFullNameP, portData->portHandle[x])); - - // Get the inital input values - if ( portData->portDir[x] != vhpiOut ) - vhpi_get_value(portData->portHandle[x], portData->portValue[x]); - - // Set the inital output values - if ( portData->portDir[x] != vhpiIn ) - vhpi_put_value(portData->portHandle[x], portData->portValue[x], vhpiForcePropagate); - } - - // Setup callback function for port 0& 1 - for (x=0; x < 1; x++) { - cbData = (vhpiCbDataT *) malloc(sizeof(vhpiCbDataT)); - cbData->reason = vhpiCbValueChange; - cbData->obj = portData->portHandle[x]; - cbData->value = portData->portValue[x]; - cbData->cbf = VhpiGenericCallBack; - cbData->time = (vhpiTimeT *) malloc(sizeof(vhpiTimeT)); - cbData->user_data = (void *)portData; - #if (VCS_VERSION >= 2016) - vhpi_register_cb(cbData, vhpiReturnCb); - #else - vhpi_register_cb(cbData); - #endif - } + vhpiCbDataT *cbData; + int width; + int x, y; + char *temp; + + // Blank out port handles and create value structures + for (x=0; x < portData->portCount; x++) { + portData->portHandle[x] = 0; + portData->portValue[x] = (vhpiValueT *) malloc(sizeof(vhpiValueT)); + portData->intValue[x] = 0; + portData->outEnable[x] = 1; + + memset(portData->portValue[x], 0, sizeof(vhpiValueT)); + } + + // Copy block name + temp = vhpi_get_str(vhpiFullNameP, compInst); + portData->blockName = (char *) malloc(strlen(temp)+1); + strcpy(portData->blockName, temp);//NOLINT + + // Get each port and verify width and direction, get initial value + for (x=0; x < portData->portCount; x++) { + // Get ID + portData->portHandle[x] = vhpi_handle_by_index(vhpiPortDecls, compInst, x); + + // Setup value types + if ( portData->portWidth[x] == 1 ) { + portData->portValue[x]->format = vhpiEnumVal; + portData->portValue[x]->value.enumval = 2; + } else { + portData->portValue[x]->format = vhpiEnumVecVal; + width = vhpi_value_size(portData->portHandle[x], vhpiEnumVecVal); + portData->portValue[x]->value.enums = (vhpiEnumT*)malloc(width); + portData->portValue[x]->bufSize = width; + for (y=0; y < portData->portWidth[x]; y++ ) + portData->portValue[x]->value.enums[y] = 2; + } + + // Check direction + if (vhpi_get(vhpiModeP, portData->portHandle[x]) != portData->portDir[x]) + vhpi_printf("Error: Port '%s' direction mismatch\n", vhpi_get_str(vhpiFullNameP, portData->portHandle[x])); + + // Check width + if (vhpi_get(vhpiSizeP, portData->portHandle[x]) != portData->portWidth[x]) + vhpi_printf("Error: Port '%s' size mismatch\n", vhpi_get_str(vhpiFullNameP, portData->portHandle[x])); + + // Get the inital input values + if ( portData->portDir[x] != vhpiOut ) + vhpi_get_value(portData->portHandle[x], portData->portValue[x]); + + // Set the inital output values + if ( portData->portDir[x] != vhpiIn ) + vhpi_put_value(portData->portHandle[x], portData->portValue[x], vhpiForcePropagate); + } + + // Setup callback function for port 0& 1 + for (x=0; x < 1; x++) { + cbData = (vhpiCbDataT *) malloc(sizeof(vhpiCbDataT)); + cbData->reason = vhpiCbValueChange; + cbData->obj = portData->portHandle[x]; + cbData->value = portData->portValue[x]; + cbData->cbf = VhpiGenericCallBack; + cbData->time = (vhpiTimeT *) malloc(sizeof(vhpiTimeT)); + cbData->user_data = (void *)portData; + #if (VCS_VERSION >= 2016) + vhpi_register_cb(cbData, vhpiReturnCb); + #else + vhpi_register_cb(cbData); + #endif + } }