diff --git a/.auto-changelog b/.auto-changelog new file mode 100644 index 0000000..d061fe9 --- /dev/null +++ b/.auto-changelog @@ -0,0 +1,4 @@ +{ + "template": "changelog.hbs", + "issuePattern": "fix.*:" +} diff --git a/.gitmodules b/.gitmodules index 400b111..1e4b6d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "deps/rabbitmq-c"] path = deps/rabbitmq-c url = https://github.com/alanxz/rabbitmq-c.git +[submodule "deps/sse2neon"] + path = deps/sse2neon + url = https://github.com/DLTcollab/sse2neon.git diff --git a/.release-it.json b/.release-it.json new file mode 100644 index 0000000..d55b72b --- /dev/null +++ b/.release-it.json @@ -0,0 +1,26 @@ +{ + "hooks": { + "before:github:release": [ + "make BUILD_REMOTE=1 BUILD_DEBUG=1 BOARD=de10nano BUILD_FPGA_ACCEL=1", + "tar zcvf remote-worker.tar.gz --directory=build remote-worker" + ] + }, + "git": { + "changelog": "npx auto-changelog --stdout", + "requireUpstream": false, + "commit": false, + "tag": true, + "tagName": "v${version}", + "push": false + }, + "github": { + "release": true, + "releaseName": "v${version}", + "preRelease": true, + "draft": true, + "tokenRef": "GITHUB_TOKEN", + "assets": [ + "remote-worker.tar.gz" + ] + } +} diff --git a/Doxyfile b/Doxyfile index afbcc02..6fe3a44 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2,7 +2,7 @@ # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = "dcurl" -PROJECT_NUMBER = 0.1.0 +PROJECT_NUMBER = 0.5.0 OUTPUT_DIRECTORY = docs OPTIMIZE_OUTPUT_FOR_C = YES #--------------------------------------------------------------------------- @@ -17,6 +17,7 @@ INPUT = . \ src FILE_PATTERNS = dcurl.c \ dcurl.h \ + cpu-utils.h \ *.md USE_MDFILE_AS_MAINPAGE = README.md #--------------------------------------------------------------------------- @@ -27,6 +28,10 @@ INLINE_SOURCES = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES #--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_STATIC = YES +#--------------------------------------------------------------------------- # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO diff --git a/Makefile b/Makefile index b9f59f1..197b778 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.4.1 +VERSION = 0.5.0 OUT ?= ./build SRC := src diff --git a/changelog.hbs b/changelog.hbs new file mode 100644 index 0000000..7369535 --- /dev/null +++ b/changelog.hbs @@ -0,0 +1,19 @@ +{{#with releases.[0]}} + + ## {{title}} {{#if niceDate}}({{niceDate}}){{/if}} + + ### :tada: New Features + + {{#commit-list merges heading="" message='feat.*: '}} + - {{{message}}} ({{commit.shorthash}}) + {{/commit-list}} + + {{#commit-list commits heading="" message='feat.*: '}} + - {{{subject}}} ({{shorthash}}) + {{/commit-list}} + + {{#commit-list fixes heading='### :bug: Bug Fixes'}} + - {{commit.subject}} ({{commit.shorthash}}) + {{/commit-list}} + +{{/with}} diff --git a/deps/sse2neon b/deps/sse2neon new file mode 160000 index 0000000..d88df33 --- /dev/null +++ b/deps/sse2neon @@ -0,0 +1 @@ +Subproject commit d88df33bb849188deec044f98d998bb6ec795803 diff --git a/docs/board-de10-nano.md b/docs/board-de10-nano.md new file mode 100644 index 0000000..bc9e77c --- /dev/null +++ b/docs/board-de10-nano.md @@ -0,0 +1,126 @@ +# Execute dcurl remote worker on the [DE10-Nano](https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&No=1046) board +## Write the image file to the micro SD card +Prepare a micro SD card reader for writing the image file. + +The command for writing the image file to the micro SD card: +### Linux +```bash +$ sudo dd if=[image-file] of=/dev/sd[x] bs=1M status=progress +``` +**Important**:\ +Please make sure to fill the correct **[x]** value in `/dev/sd[x]`.\ +It must map to the micro SD card. Otherwise, your hard disk will be broken.\ +You can check it with the command `$ sudo fdisk -l`. + +### macOS +```bash +$ sudo dd if=[image-file] of=/dev/mmcblk[x] bs=1M status=progress +``` +**Important**:\ +Please make sure to fill the correct **[x]** value in `/dev/mmcblk[x]`. + + +## Hardware manual setting +Change the FPGA configuration mode switch as shown in the image\ + + + +## Connect with the De10-Nano board +### Hardware +Please make sure the following list are well set or connected: +- 5V DC Power Jack +- UART to USB (USB Mini-B) +- HPS Gigabit Ethernet +- MicroSD Card Socket + + + +### Minicom +Use **minicom** to connect with the **DE10-Nano** board. +#### Install minicom +##### Linux +```bash +$ sudo apt install minicom +``` +##### macOS +```bash +$ sudo brew install minicom +``` + +#### Configure minicom +```bash +$ sudo minicom -s +``` +Select **Serial port setup** and configure as the following +##### Linux +``` +┌─────────────────────────────────────────────────────────────────┐ +│ A - Serial Device : /dev/ttyUSB0 │ +│ B - Lockfile Location : /var/lock │ +│ C - Callin Program : │ +│ D - Callout Program : │ +│ E - Bps/Par/Bits : 115200 8N1 │ +│ F - Hardware Flow Control : No │ +│ G - Software Flow Control : No │ +│ │ +│ Change which setting? │ +└─────────────────────────────────────────────────────────────────┘ +``` + +##### macOS +``` +┌─────────────────────────────────────────────────────────────────┐ +│ A - Serial Device : /dev/tty.usbserial-A107T0EA │ +│ B - Lockfile Location : /usr/local/Cellar/minicom/2.7.1/var │ +│ C - Callin Program : │ +│ D - Callout Program : │ +│ E - Bps/Par/Bits : 115200 8N1 │ +│ F - Hardware Flow Control : No │ +│ G - Software Flow Control : No │ +│ │ +│ Change which setting? │ +└─────────────────────────────────────────────────────────────────┘ +``` + +If you want to change the value of `Serial Device`, press **Ctrl-A**. + +After configuration, select **Save setup as dfl** and select **Exit from Minicom** to exit. + +#### Connect with minicom +```bash +$ sudo minicom +``` +Then enter the user account and the password to login. + + +## Build and execute the remote worker +### Load the driver +You need to load the driver first for the further execution of the remote worker.\ +Otherwise, it will crash. +```bash +$ sudo insmod cpowdrv.ko +``` + +### Clone the repository +```bash +$ git clone git@github.com:DLTcollab/dcurl.git +``` + +### Build the remote worker +```bash +$ cd dcurl +$ make BUILD_REMOTE=1 BOARD=de10nano BUILD_FPGA_ACCEL=1 +``` + +### Execute the remote worker +```bash +$ sudo ./build/remote-worker --broker [rabbitmq-broker-hostname] +``` +Use **-b** or **--broker** to assign the hostname of the RabbitMQ broker.\ +The default value is **localhost**. + + +## Reference +- [Terasic DE10-Nano Product Brief](https://www.mouser.tw/pdfdocs/de10NanoBrief.pdf) +- [Terasic DE10-Nano Get Started Guide](https://software.intel.com/en-us/terasic-de10-nano-get-started-guide) +- [Linux on ARM - DE10-Nano Kit](https://www.digikey.com/eewiki/display/linuxonarm/DE10-Nano+Kit) diff --git a/docs/fpga-accelerator.md b/docs/fpga-accelerator.md old mode 100755 new mode 100644 diff --git a/docs/release-workflow.md b/docs/release-workflow.md new file mode 100644 index 0000000..4028341 --- /dev/null +++ b/docs/release-workflow.md @@ -0,0 +1,20 @@ +# Release Workflow + +The motivation of release workfow is to update the GitHub release page +when there is a new tag pushed to the GitHub. + +The release workflow uses `auto-changelog` utility to generate the +changelog, then use `release-it` utility to publish the changelog +on the release page. + +The `release-it` will also build the `remote-worker`, and upload the +packed the `remote-worker` to release page. + +- `.release-it`: `release-it` configuration file +- `.auto-changelog`: `auto-changelog` configuration file +- `changelog.hbs`: changelog template file + +## Reference + +- [release-it/release-it](https://github.com/release-it/release-it) +- [CookPete/auto-changelog](https://github.com/CookPete/auto-changelog) diff --git a/docs/remote-interface.md b/docs/remote-interface.md index 61b89d2..557385d 100644 --- a/docs/remote-interface.md +++ b/docs/remote-interface.md @@ -43,6 +43,9 @@ Here are detailed implementations of the RabbitMQ-provided RPC pattern as follow * An asynchronous RPC uses a connection to RabbitMQ broker * Remote workers can obtain requests from `incoming_queue` by default exchange of RabbitMQ broker +The remote worker can be executed on the different hardwares and do the PoW.\ +For executing it on DE10-Nano board, please read the [docs/board-de10-nano.md](board-de10-nano.md). + ## How to test remote interface in localhost You need to open three terminals diff --git a/docs/threading-model.md b/docs/threading-model.md index caf79e1..f644c83 100644 --- a/docs/threading-model.md +++ b/docs/threading-model.md @@ -2,13 +2,10 @@ In `dcurl`, it calls the APIs provided by the `libtuv` submodule to use the threads and thread pool. ## Thread pool size -The thread pool size initialization is written in the function `init_once()`.\ -The environment variable `UV_THREADPOOL_SIZE` can be used to overwrite the default pool size.\ +The thread pool size can be set with the function `uv_set_threadpool_size()`.\ Default pool size: 4\ Maximum pool size: 128 -The current `dcurl` implementation can not affect the thread pool size. - ## Thread pool mechanism The thread pool and the work request queue are global.\ Work request can be treated as the function you would like to request the thread to execute. diff --git a/mk/submodule.mk b/mk/submodule.mk index a027d74..566c029 100644 --- a/mk/submodule.mk +++ b/mk/submodule.mk @@ -54,11 +54,21 @@ endif cd $(LIBRABBITMQ_PATH)/build && \ cmake --build . +# sse2neon related variables +SSE2NEON_PATH = deps/sse2neon +SSE2NEON_INCLUDE := -I $(SSE2NEON_PATH) + +$(SSE2NEON_PATH)/sse2neon.h: + git submodule update --init $(SSE2NEON_PATH) + # Submodules SUBS := $(LIBTUV_PATH)/include ifeq ($(BUILD_REMOTE),1) SUBS += $(LIBRABBITMQ_PATH)/librabbitmq endif +ifeq ($(UNAME_M),$(filter $(UNAME_M),arm aarch64)) + SUBS += $(SSE2NEON_PATH)/sse2neon.h +endif # Submodule related objects SUB_OBJS := $(LIBTUV_OBJS) ifeq ($(BUILD_REMOTE),1) @@ -69,3 +79,6 @@ SUB_INCLUDE := $(LIBTUV_INCLUDE) ifeq ($(BUILD_REMOTE),1) SUB_INCLUDE += $(LIBRABBITMQ_INCLUDE) endif +ifeq ($(UNAME_M),$(filter $(UNAME_M),arm aarch64)) + SUB_INCLUDE += $(SSE2NEON_INCLUDE) +endif diff --git a/src/common.h b/src/common.h index 3595d16..9288133 100644 --- a/src/common.h +++ b/src/common.h @@ -15,8 +15,8 @@ #include #define __DCURL_MAJOR__ 0 -#define __DCURL_MINOR__ 4 -#define __DCURL_PATCH__ 1 +#define __DCURL_MINOR__ 5 +#define __DCURL_PATCH__ 0 double diff_in_second(struct timespec t1, struct timespec t2); diff --git a/src/cpu-utils.h b/src/cpu-utils.h index 52f308c..754fdcb 100644 --- a/src/cpu-utils.h +++ b/src/cpu-utils.h @@ -15,6 +15,11 @@ #include #endif +/** + * @file cpu-utils.h + * @brief Utility functions for acquiring CPU information. + */ + /* On Mac OS X, define our own get_nprocs_conf() */ #if defined(__APPLE__) || defined(__FreeBSD__) #include @@ -28,9 +33,87 @@ static unsigned int get_nprocs_conf() } #endif -static inline int get_avail_nprocs() +/** + * @brief Get the thread number per physical processor. + * + * - GNU/Linux: Acquire the thread number by parsing the CPU information. + * - macOS: Acquire the thread number by doing the calculation of + * (logical processor number / physical processor number). + * @return The thread number per physical processor. + * @retval 1 Hyperthreading disabled. + * @retval 2 Hyperthreading enabled. + * @retval -1 Unexpected error. + */ +static inline int get_nthds_per_phys_proc() +{ + FILE *fd; + int nthread; +#if defined(__linux__) + char nthd[4]; + + fd = popen("LC_ALL=C lscpu | grep 'Thread(s) per core' | awk '{printf $4}'", + "r"); + if (fd == NULL) + return -1; + if (fgets(nthd, sizeof(nthd), fd) == NULL) + return -1; + nthread = (int) strtol(nthd, NULL, 10); + if (errno == ERANGE || nthread == 0) { + return -1; + } +#elif defined(__APPLE__) + char p_proc[4], l_proc[4]; + int phys_proc, logic_proc; + + fd = popen("sysctl hw.physicalcpu | awk '{printf $2}'", "r"); + if (fd == NULL) + return -1; + if (fgets(p_proc, sizeof(p_proc), fd) == NULL) + return -1; + fd = popen("sysctl hw.logicalcpu | awk '{printf $2}'", "r"); + if (fd == NULL) + return -1; + if (fgets(l_proc, sizeof(l_proc), fd) == NULL) + return -1; + phys_proc = (int) strtol(p_proc, NULL, 10); + if (errno == ERANGE || phys_proc == 0) { + return -1; + } + logic_proc = (int) strtol(l_proc, NULL, 10); + if (errno == ERANGE || logic_proc == 0) { + return -1; + } + + nthread = logic_proc / phys_proc; +#endif + + if (pclose(fd) == -1) + return -1; + return nthread; +} + +/** + * @brief Get the available number of physical processor. + * + * Detect the physical processor number with `get_nproc_conf()` + * or get the number with the environment variable **DCURL_NUM_CPU**. + * @return The available number of physical processor. + * @retval DCURL_NUM_CPU Return it if the environment variable + * **DCURL_NUM_CPU** is set. + * @retval Maximum_physical_processor_number-1 Return it if the environment + * variable **DCURL_NUM_CPU** is not set. The minimum value would be 1. + * @retval -1 Unexpected error. + */ +static inline int get_avail_phys_nprocs() { - size_t nproc = get_nprocs_conf() - 1; + int nthd; + size_t nproc; + + nthd = get_nthds_per_phys_proc(); + if (nthd <= 0) + return -1; + else + nproc = (get_nprocs_conf() / nthd) - 1; do { char *env_ncpu = getenv("DCURL_NUM_CPU"); diff --git a/src/dcurl.c b/src/dcurl.c index cb54bec..fae5388 100644 --- a/src/dcurl.c +++ b/src/dcurl.c @@ -126,6 +126,14 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) remote_pow: if (!doRemoteContext(&Remote_Context, pow_ctx)) { + /* The remote interface can not work without activated RabbitMQ broker + * and remote worker. If it is not working, the PoW would be calculated + * by the local machine. And the remote interface resource should be + * released. + */ + freeRemoteContext(&Remote_Context, pow_ctx); + exitRemoteContext(&Remote_Context); + uv_sem_post(¬ify_remote); goto local_pow; } else { res = getRemoteResult(&Remote_Context, pow_ctx); diff --git a/src/pow_avx.c b/src/pow_avx.c index dbc7325..d928530 100644 --- a/src/pow_avx.c +++ b/src/pow_avx.c @@ -573,7 +573,8 @@ static bool PowAVX(void *pow_ctx) static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) { - int nproc = get_avail_nprocs(); + impl_ctx->num_max_thread = get_nthds_per_phys_proc(); + int nproc = get_avail_phys_nprocs(); if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; @@ -609,7 +610,7 @@ static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; uv_loop_init(&ctx[i].loop); } - uv_set_threadpool_size(nproc); + uv_set_threadpool_size(impl_ctx->num_max_thread * nproc); impl_ctx->context = ctx; uv_mutex_init(&impl_ctx->lock); return true; @@ -693,7 +694,7 @@ ImplContext PoWAVX_Context = { .context = NULL, .description = "CPU (Intel AVX)", .bitmap = 0, - .num_max_thread = 2, + .num_max_thread = 0, .num_working_thread = 0, .initialize = PoWAVX_Context_Initialize, .destroy = PoWAVX_Context_Destroy, diff --git a/src/pow_c.c b/src/pow_c.c index 910bcdb..9c4c155 100644 --- a/src/pow_c.c +++ b/src/pow_c.c @@ -337,7 +337,8 @@ bool PowC(void *pow_ctx) static bool PoWC_Context_Initialize(ImplContext *impl_ctx) { - int nproc = get_avail_nprocs(); + impl_ctx->num_max_thread = get_nthds_per_phys_proc(); + int nproc = get_avail_phys_nprocs(); if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; @@ -373,7 +374,7 @@ static bool PoWC_Context_Initialize(ImplContext *impl_ctx) impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; uv_loop_init(&ctx[i].loop); } - uv_set_threadpool_size(nproc); + uv_set_threadpool_size(impl_ctx->num_max_thread * nproc); impl_ctx->context = ctx; uv_mutex_init(&impl_ctx->lock); return true; @@ -456,7 +457,7 @@ ImplContext PoWC_Context = { .context = NULL, .description = "CPU (Pure C)", .bitmap = 0, - .num_max_thread = 2, + .num_max_thread = 0, .num_working_thread = 0, .initialize = PoWC_Context_Initialize, .destroy = PoWC_Context_Destroy, diff --git a/src/pow_sse.c b/src/pow_sse.c index a6a0a2a..8bb9567 100644 --- a/src/pow_sse.c +++ b/src/pow_sse.c @@ -355,7 +355,8 @@ static bool PowSSE(void *pow_ctx) static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) { - int nproc = get_avail_nprocs(); + impl_ctx->num_max_thread = get_nthds_per_phys_proc(); + int nproc = get_avail_phys_nprocs(); if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; @@ -391,7 +392,7 @@ static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; uv_loop_init(&ctx[i].loop); } - uv_set_threadpool_size(nproc); + uv_set_threadpool_size(impl_ctx->num_max_thread * nproc); impl_ctx->context = ctx; uv_mutex_init(&impl_ctx->lock); return true; @@ -475,7 +476,7 @@ ImplContext PoWSSE_Context = { .context = NULL, .description = "CPU (Intel SSE)", .bitmap = 0, - .num_max_thread = 2, + .num_max_thread = 0, .num_working_thread = 0, .initialize = PoWSSE_Context_Initialize, .destroy = PoWSSE_Context_Destroy, diff --git a/src/remote_common.c b/src/remote_common.c index 12c1545..f5178d2 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -64,15 +64,16 @@ bool die_on_error(int x, char const *context) return true; } -bool connect_broker(amqp_connection_state_t *conn) +bool connect_broker(amqp_connection_state_t *conn, const char *hostName) { amqp_socket_t *socket = NULL; + const char *host = (hostName != NULL) ? hostName : "localhost"; /* Connect to the rabbitmq broker */ *conn = amqp_new_connection(); socket = amqp_tcp_socket_new(*conn); - if (amqp_socket_open(socket, HOSTNAME, 5672) != AMQP_STATUS_OK) { - ddprintf("%s\n", "The rabbitmq broker is closed"); + if (amqp_socket_open(socket, host, 5672) != AMQP_STATUS_OK) { + ddprintf("The rabbitmq broker of %s is closed\n", host); goto destroy_connection; } @@ -85,7 +86,7 @@ bool connect_broker(amqp_connection_state_t *conn) /* Open the channel in the rabbitmq broker */ amqp_channel_open(*conn, 1); - if (!(die_on_amqp_error(amqp_get_rpc_reply(*conn), "Opennng the channel"))) + if (!(die_on_amqp_error(amqp_get_rpc_reply(*conn), "Opening the channel"))) goto channel_close; return true; @@ -258,7 +259,7 @@ bool wait_response_message(amqp_connection_state_t *conn, body_received += frame.payload.body_fragment.len; } if (body_received != body_target) { - ddprintf("Received body is small than body target\n"); + ddprintf("Received body is smaller than body target\n"); return false; } diff --git a/src/remote_common.h b/src/remote_common.h index cb1805e..2e6797a 100644 --- a/src/remote_common.h +++ b/src/remote_common.h @@ -14,10 +14,9 @@ #include "amqp.h" #include "amqp_tcp_socket.h" -#define HOSTNAME "localhost" #define MSG_PREFIX "[dcurl-remote] " -bool connect_broker(amqp_connection_state_t *conn); +bool connect_broker(amqp_connection_state_t *conn, const char *hostName); bool declare_queue(amqp_connection_state_t *conn, amqp_channel_t channel, diff --git a/src/remote_interface.c b/src/remote_interface.c index da326c4..f9245a7 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -108,7 +108,7 @@ static bool Remote_doPoW(RemoteImplContext *remote_ctx, void *pow_ctx) /* Message body format: transacton | mwm */ memcpy(messagebody, ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); - sprintf(buf, "%d", ctx->mwm); + snprintf(buf, sizeof(buf), "%d", ctx->mwm); memcpy(messagebody + TRANSACTION_TRYTES_LENGTH, buf, 4); if (!declare_callback_queue(&remote_ctx->conn[ctx->indexOfContext], 1, @@ -146,7 +146,7 @@ static bool Remote_init(RemoteImplContext *remote_ctx) memset(remote_ctx->slots, 0, remote_ctx->num_max_thread * sizeof(bool)); for (int i = 0; i < CONN_MAX; i++) { - if (!connect_broker(&remote_ctx->conn[i])) + if (!connect_broker(&remote_ctx->conn[i], NULL)) goto fail_to_init; } if (!declare_queue(&remote_ctx->conn[0], 1, "incoming_queue")) diff --git a/src/remote_worker.c b/src/remote_worker.c index f8df527..d397dfa 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -6,23 +6,45 @@ * "LICENSE" at the root of this distribution. */ +#include #include "common.h" #include "constants.h" #include "dcurl.h" #include "remote_common.h" -int main(int argc, char const *const *argv) +int main(int argc, char *const *argv) { char trytes[TRANSACTION_TRYTES_LENGTH]; char buf[4]; int mwm; + int cmdOpt; + int optIdx; + const struct option longOpt[] = {{"broker", required_argument, NULL, 'b'}, + {NULL, 0, NULL, 0}}; amqp_connection_state_t conn; amqp_envelope_t envelope; + char *hostIP = NULL; + + /* Parse the command line options */ + /* TODO: Support macOS since getopt_long() is GNU extension */ + while (1) { + cmdOpt = getopt_long(argc, argv, "b:", longOpt, &optIdx); + if (cmdOpt == -1) + break; + + /* Invalid option */ + if (cmdOpt == '?') + break; + + if (cmdOpt == 'b') { + hostIP = optarg; + } + } dcurl_init(); - if (!connect_broker(&conn)) + if (!connect_broker(&conn, hostIP)) goto fail; if (!set_consuming_queue(&conn, 1, "incoming_queue")) diff --git a/src/trinary.c b/src/trinary.c index ad75e85..17187cc 100644 --- a/src/trinary.c +++ b/src/trinary.c @@ -7,7 +7,7 @@ */ #include "trinary.h" -#if defined(__SSE4_2__) +#if defined(__SSE4_2__) || defined(__ARM_NEON) #include "trinary_sse42.h" #endif #include @@ -35,7 +35,7 @@ static bool validateTrits(Trobject_t *trits) if (trits->type != TYPE_TRITS) return false; -#if defined(__SSE4_2__) +#if defined(__SSE4_2__) || defined(__ARM_NEON) return validateTrits_sse42(trits); #endif for (int i = 0; i < trits->len; i++) diff --git a/src/trinary_sse42.h b/src/trinary_sse42.h index 9f4684f..e379d06 100644 --- a/src/trinary_sse42.h +++ b/src/trinary_sse42.h @@ -9,8 +9,16 @@ #ifndef TRINARY_SSE42_H_ #define TRINARY_SSE42_H_ +#if defined(__SSE4_2__) #include +#endif #include "constants.h" +#if defined(__ARM_NEON) +#include "sse2neon.h" +#endif +#if !defined(__SSE4_2__) && !defined(__ARM_NEON) +#error "The hardware architecture should support SSE4.2 or NEON instruction." +#endif #define BLOCK_8BIT(type) (sizeof(type) / sizeof(int8_t)) #define BYTE_OF_128BIT 16 @@ -66,6 +74,7 @@ static inline bool validateTrits_sse42(Trobject_t *trits) return true; } +#if defined(__SSE4_2__) static inline bool validateTrytes_sse42(Trobject_t *trytes) { const int block_8bit = BLOCK_8BIT(__m128i); @@ -452,5 +461,6 @@ static inline Trobject_t *trits_from_trytes_sse42(Trobject_t *trytes) return trits; } +#endif // #if defined(__SSE4_2__) #endif