From a2f2e90f2d01506bd33f72032ba0c09ef0ac727d Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Mon, 22 Apr 2024 15:42:10 -0700 Subject: [PATCH 01/11] ADD: add initial SimUDP periperhal --- src/sim_udp.cc | 89 ++++++++++++++++++++++++++++++ src/sim_udp.h | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+) create mode 100644 src/sim_udp.cc create mode 100644 src/sim_udp.h diff --git a/src/sim_udp.cc b/src/sim_udp.cc new file mode 100644 index 0000000..12fbd57 --- /dev/null +++ b/src/sim_udp.cc @@ -0,0 +1,89 @@ +#include "sim_udp.h" + +bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { + if (addr >= 0x1000 || len > 4) return false; + uint32_t r = 0; + switch (addr) { + case UART_TXFIFO: r = 0x0 ; break; + case UART_RXFIFO: r = read_rxfifo(); break; + case UART_TXCTRL: r = txctrl ; break; + case UART_RXCTRL: r = rxctrl ; break; + case UART_IE: r = ie ; break; + case UART_IP: r = read_ip() ; break; + case UART_DIV: r = div ; break; + case ETH_ADDR_IP: r = reg_addr_ip ; break; + case ETH_ADDR_PORT: r = reg_addr_port; break; + default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); + } + memcpy(bytes, &r, len); + return true; +} + + +bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { + if (addr >= 0x1000 || len > 4) return false; + switch (addr) { + case UART_TXFIFO: canonical_terminal_t::write(*bytes); return true; + case UART_TXCTRL: memcpy(&txctrl, bytes, len); return true; + case UART_RXCTRL: memcpy(&rxctrl, bytes, len); return true; + case UART_IE: memcpy(&ie, bytes, len); update_interrupts(); return true; + case UART_DIV: memcpy(&div, bytes, len); return true; + case ETH_ADDR_IP: memcpy(®_addr_ip, bytes, len); return true; + case ETH_ADDR_PORT: memcpy(®_addr_port, bytes, len); return true; + default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); + } +} + +void sim_udp_t::tick(reg_t UNUSED rtc_ticks) { + if (rx_fifo.size() >= UART_RX_FIFO_SIZE) return; + int rc = canonical_terminal_t::read(); + if (rc < 0) return; + rx_fifo.push((uint8_t)rc); + update_interrupts(); +} + +int SimUDP_parseFDT(const void *fdt, reg_t *address, + const char *compatible) { + int nodeoffset, len, rc; + const fdt32_t *reg_p; + + nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compatible); + if (nodeoffset < 0) + return nodeoffset; + + rc = fdt_get_node_addr_size(fdt, nodeoffset, address, NULL, "reg"); + if (rc < 0 || !address) + return -ENODEV; + + return 0; +} + + +// This function parses an instance of this device from the FDT +// An FDT node for a device should encode, at minimum, the base address for the device +sim_udp_t* SimUDP_parseFromFDT(const void* fdt, const sim_t* sim, reg_t* base, std::vector sargs) { + if (SimUDP_parseFDT(fdt, base, "ucbbar,sim_udp") == 0) { + printf("Found SimUDP at %lx\n", *base); + return new sim_udp_t(sim->get_intctrl(), 1); + } else { + return nullptr; + } +} + +std::string SimUDP_generateDTS(const sim_t* sim) { + std::stringstream s; + s << std::hex + << " udp: udp@" << 0x10001000 << " {\n" + " compatible = \"ucbbar,sim_udp\";\n" + " interrupt-parent = <&PLIC>;\n" + " interrupts = <" << std::dec << 2; + reg_t blkdevbs = 0x10001000; + reg_t blkdevsz = 0x1000; + s << std::hex << ">;\n" + " reg = <0x" << (blkdevbs >> 32) << " 0x" << (blkdevbs & (uint32_t)-1) << + " 0x" << (blkdevsz >> 32) << " 0x" << (blkdevsz & (uint32_t)-1) << ">;\n" + " };\n"; + return s.str(); +} + +REGISTER_DEVICE(sim_udp, SimUDP_parseFromFDT, SimUDP_generateDTS); diff --git a/src/sim_udp.h b/src/sim_udp.h new file mode 100644 index 0000000..f661c1b --- /dev/null +++ b/src/sim_udp.h @@ -0,0 +1,147 @@ +#ifndef _SIM_UDP_H +#define _SIM_UDP_H + +#include +#include +#include +#include +#include + + + +#include +#include +#include +#include +#include +#include + + + +#define UART_TXFIFO (0x00) +#define UART_RXFIFO (0x04) +#define UART_TXCTRL (0x08) +#define UART_TXMARK (0x0a) +#define UART_RXCTRL (0x0c) +#define UART_RXMARK (0x0e) + +#define ETH_ADDR_IP 0x50 +#define ETH_ADDR_PORT 0x54 + + +#define UART_IE (0x10) +#define UART_IP (0x14) +#define UART_DIV (0x18) +#define UART_PARITY (0x1c) +#define UART_WIRE4 (0x20) +#define UART_EITHER8OR9 (0x24) + +#define UART_GET_TXCNT(txctrl) ((txctrl >> 16) & 0x7) +#define UART_GET_RXCNT(rxctrl) ((rxctrl >> 16) & 0x7) +#define UART_RX_FIFO_SIZE (8) + +#define UART_IE_TXWM (1) +#define UART_IE_RXWM (2) + +#define UART_IP_TXWM (1) +#define UART_IP_RXWM (2) + + + +typedef struct { + int sockfd; + pthread_t thread_id; + struct sockaddr_in client_addr; + struct sockaddr_in host_addr; + float obs[1]; +} UDPRx; + +class sim_udp_t : public abstract_device_t { +public: + sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) : + ie(0), ip(0), txctrl(0), rxctrl(0), div(0), interrupt_id(int_id), intctrl(intctrl) { + + // host ip + char *host_ip = "127.0.0.1"; + int host_port = 8000; + + + udp = (UDPRx *)malloc(sizeof(UDPRx)); + + memset(&udp->client_addr, 0, sizeof(udp->client_addr)); + memset(&udp->host_addr, 0, sizeof(udp->host_addr)); + memset(udp->obs, 0, 1 * sizeof(float)); + + udp->host_addr.sin_family = AF_INET; + udp->host_addr.sin_addr.s_addr = inet_addr(host_ip); + udp->host_addr.sin_port = htons(host_port); + + + // Create socket file descriptor + if ((udp->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf("[ERROR]: socket creation failed"); + } + + // if (bind(udp->sockfd, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)) < 0 ) { + // printf("[ERROR]: bind failed"); + // } + + char tx_buffer[] = "Hello from the other side\n"; + + sendto(udp->sockfd, tx_buffer, sizeof(tx_buffer), 0, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)); + + // Create a thread running the receive() function + + printf("[INFO]: Receive thread created, thread ID: %ld\n", (long)udp->thread_id); + + + + } + + bool load(reg_t addr, size_t len, uint8_t* bytes) override; + bool store(reg_t addr, size_t len, const uint8_t* bytes) override; + void tick(reg_t UNUSED rtc_ticks) override; + +private: + std::queue rx_fifo; + uint32_t ie; + uint32_t ip; + uint32_t txctrl; + uint32_t rxctrl; + uint32_t div; + reg_t interrupt_id; + abstract_interrupt_controller_t *intctrl; + + uint32_t reg_addr_ip; + uint32_t reg_addr_port; + + UDPRx *udp; + + uint64_t read_ip() { + uint64_t ret = 0; + uint64_t txcnt = UART_GET_TXCNT(txctrl); + uint64_t rxcnt = UART_GET_RXCNT(rxctrl); + if (txcnt != 0) ret |= UART_IP_TXWM; + if (rx_fifo.size() > rxcnt) ret |= UART_IP_RXWM; + return ret; + } + + uint32_t read_rxfifo() { + if (!rx_fifo.size()) return 0x80000000; + uint8_t r = rx_fifo.front(); + rx_fifo.pop(); + update_interrupts(); + return r; + } + + void update_interrupts() { + int cond = 0; + if ((ie & UART_IE_TXWM) || + ((ie & UART_IE_RXWM) && rx_fifo.size())) { + cond = 1; + } + intctrl->set_interrupt_level(interrupt_id, (cond) ? 1 : 0); + } +}; + +#endif // _SIM_UDP_H From 3707fa0d98c273351d5017d3ec1086b61f89a854 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Thu, 27 Jun 2024 00:06:44 -0700 Subject: [PATCH 02/11] ADD: stage --- src/sim_udp.cc | 76 ++++++++++++++++++++++++++++---------- src/sim_udp.h | 99 ++++++++++++-------------------------------------- 2 files changed, 81 insertions(+), 94 deletions(-) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index 12fbd57..eaf8aec 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -1,19 +1,49 @@ #include "sim_udp.h" + +void sim_udp_t::write_udp_tx() { + printf(" [INFO]: Writing UDP TX with DMA pointer: 0x%lx, DMA size: %d\n", tx_fifo, reg_tx_size); + printf("addr: %x, port: %x\n", reg_addr_ip, reg_addr_tx_port); + sendto(udp->sockfd, (uint8_t *)tx_fifo, reg_tx_size, 0, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)); +} + +void sim_udp_t::create_udp_tx() { + udp = (UDPRx *)malloc(sizeof(UDPRx)); + + memset(&udp->client_addr, 0, sizeof(udp->client_addr)); + memset(&udp->host_addr, 0, sizeof(udp->host_addr)); + + // host ip + udp->host_addr.sin_family = AF_INET; + udp->host_addr.sin_addr.s_addr = htonl(reg_addr_ip); + udp->host_addr.sin_port = htons(reg_addr_tx_port); + + + // Create socket file descriptor + if ((udp->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf(" [ERROR]: socket creation failed\n"); + } + + // if (bind(udp->sockfd, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)) < 0) { + // printf(" [ERROR]: bind failed\n"); + // } + + // Create a thread running the receive() function + + printf(" [INFO]: Tx thread created, thread ID: %ld\n", (long)udp->thread_id); + +} + + bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { if (addr >= 0x1000 || len > 4) return false; uint32_t r = 0; switch (addr) { - case UART_TXFIFO: r = 0x0 ; break; - case UART_RXFIFO: r = read_rxfifo(); break; - case UART_TXCTRL: r = txctrl ; break; - case UART_RXCTRL: r = rxctrl ; break; - case UART_IE: r = ie ; break; - case UART_IP: r = read_ip() ; break; - case UART_DIV: r = div ; break; - case ETH_ADDR_IP: r = reg_addr_ip ; break; - case ETH_ADDR_PORT: r = reg_addr_port; break; - default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); + case UDP_IP: r = reg_addr_ip; break; + case UDP_RXPORT: r = reg_addr_rx_port; break; + case UDP_TXPORT: r = reg_addr_tx_port; break; + case UDP_RXSIZE: r = reg_rx_size; break; + default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); return true; @@ -21,21 +51,29 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { + printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); + if (addr >= 0x1000 || len > 4) return false; + + if (addr >= UDP_TXFIFO) { + tx_fifo[addr - UDP_TXFIFO] = bytes[0]; + return true; + } switch (addr) { - case UART_TXFIFO: canonical_terminal_t::write(*bytes); return true; - case UART_TXCTRL: memcpy(&txctrl, bytes, len); return true; - case UART_RXCTRL: memcpy(&rxctrl, bytes, len); return true; - case UART_IE: memcpy(&ie, bytes, len); update_interrupts(); return true; - case UART_DIV: memcpy(&div, bytes, len); return true; - case ETH_ADDR_IP: memcpy(®_addr_ip, bytes, len); return true; - case ETH_ADDR_PORT: memcpy(®_addr_port, bytes, len); return true; - default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); + case UDP_IP: reg_addr_ip = *((uint32_t *)bytes); return true; + case UDP_RXPORT: reg_addr_rx_port = *((uint16_t *)bytes); return true; + case UDP_TXPORT: reg_addr_tx_port = *((uint16_t *)bytes); return true; + case UDP_TXCTRL: + if (bytes[0] == 1) write_udp_tx(); + if (bytes[0] == 2) create_udp_tx(); + return true; + case UDP_TXSIZE: reg_tx_size = *((uint32_t *)bytes); return true; + default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } } void sim_udp_t::tick(reg_t UNUSED rtc_ticks) { - if (rx_fifo.size() >= UART_RX_FIFO_SIZE) return; + if (rx_fifo.size() >= 1) return; int rc = canonical_terminal_t::read(); if (rc < 0) return; rx_fifo.push((uint8_t)rc); diff --git a/src/sim_udp.h b/src/sim_udp.h index f661c1b..e3b4924 100644 --- a/src/sim_udp.h +++ b/src/sim_udp.h @@ -18,34 +18,17 @@ -#define UART_TXFIFO (0x00) -#define UART_RXFIFO (0x04) -#define UART_TXCTRL (0x08) -#define UART_TXMARK (0x0a) -#define UART_RXCTRL (0x0c) -#define UART_RXMARK (0x0e) - -#define ETH_ADDR_IP 0x50 -#define ETH_ADDR_PORT 0x54 - - -#define UART_IE (0x10) -#define UART_IP (0x14) -#define UART_DIV (0x18) -#define UART_PARITY (0x1c) -#define UART_WIRE4 (0x20) -#define UART_EITHER8OR9 (0x24) - -#define UART_GET_TXCNT(txctrl) ((txctrl >> 16) & 0x7) -#define UART_GET_RXCNT(rxctrl) ((rxctrl >> 16) & 0x7) -#define UART_RX_FIFO_SIZE (8) - -#define UART_IE_TXWM (1) -#define UART_IE_RXWM (2) - -#define UART_IP_TXWM (1) -#define UART_IP_RXWM (2) - +#define UDP_IP 0x00 +#define UDP_RXPORT 0x04 +#define UDP_TXPORT 0x08 +#define UDP_RXCTRL 0x0C +#define UDP_TXCTRL 0x10 +#define UDP_RXSTATUS 0x14 +#define UDP_TXSTATUS 0x18 +#define UDP_RXSIZE 0x1C +#define UDP_TXSIZE 0x20 +#define UDP_RXFIFO 0x30 +#define UDP_TXFIFO 0x130 typedef struct { @@ -53,7 +36,6 @@ typedef struct { pthread_t thread_id; struct sockaddr_in client_addr; struct sockaddr_in host_addr; - float obs[1]; } UDPRx; class sim_udp_t : public abstract_device_t { @@ -61,70 +43,37 @@ class sim_udp_t : public abstract_device_t { sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) : ie(0), ip(0), txctrl(0), rxctrl(0), div(0), interrupt_id(int_id), intctrl(intctrl) { - // host ip - char *host_ip = "127.0.0.1"; - int host_port = 8000; - - - udp = (UDPRx *)malloc(sizeof(UDPRx)); - - memset(&udp->client_addr, 0, sizeof(udp->client_addr)); - memset(&udp->host_addr, 0, sizeof(udp->host_addr)); - memset(udp->obs, 0, 1 * sizeof(float)); - - udp->host_addr.sin_family = AF_INET; - udp->host_addr.sin_addr.s_addr = inet_addr(host_ip); - udp->host_addr.sin_port = htons(host_port); - - - // Create socket file descriptor - if ((udp->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - printf("[ERROR]: socket creation failed"); } - // if (bind(udp->sockfd, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)) < 0 ) { - // printf("[ERROR]: bind failed"); - // } - - char tx_buffer[] = "Hello from the other side\n"; - - sendto(udp->sockfd, tx_buffer, sizeof(tx_buffer), 0, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)); - - // Create a thread running the receive() function - - printf("[INFO]: Receive thread created, thread ID: %ld\n", (long)udp->thread_id); - - - - } - bool load(reg_t addr, size_t len, uint8_t* bytes) override; bool store(reg_t addr, size_t len, const uint8_t* bytes) override; void tick(reg_t UNUSED rtc_ticks) override; private: std::queue rx_fifo; + uint32_t ie; uint32_t ip; uint32_t txctrl; uint32_t rxctrl; + + uint8_t tx_fifo[256]; + + uint32_t reg_rx_size; + uint32_t reg_tx_size; + uint32_t div; reg_t interrupt_id; abstract_interrupt_controller_t *intctrl; uint32_t reg_addr_ip; - uint32_t reg_addr_port; + uint32_t reg_addr_rx_port; + uint32_t reg_addr_tx_port; UDPRx *udp; - uint64_t read_ip() { - uint64_t ret = 0; - uint64_t txcnt = UART_GET_TXCNT(txctrl); - uint64_t rxcnt = UART_GET_RXCNT(rxctrl); - if (txcnt != 0) ret |= UART_IP_TXWM; - if (rx_fifo.size() > rxcnt) ret |= UART_IP_RXWM; - return ret; - } + void write_udp_tx(); + void create_udp_tx(); uint32_t read_rxfifo() { if (!rx_fifo.size()) return 0x80000000; @@ -136,8 +85,8 @@ class sim_udp_t : public abstract_device_t { void update_interrupts() { int cond = 0; - if ((ie & UART_IE_TXWM) || - ((ie & UART_IE_RXWM) && rx_fifo.size())) { + if ((ie) || + ((ie) && rx_fifo.size())) { cond = 1; } intctrl->set_interrupt_level(interrupt_id, (cond) ? 1 : 0); From f4584bf0549852f8e05141e4d9f8b4d0ef668940 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Thu, 27 Jun 2024 11:14:29 -0700 Subject: [PATCH 03/11] ADD: add RX functionality --- src/sim_udp.cc | 176 +++++++++++++++++++++++++++++++++++++++---------- src/sim_udp.h | 111 +++++++++++++++++-------------- 2 files changed, 203 insertions(+), 84 deletions(-) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index eaf8aec..09b94b3 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -1,48 +1,134 @@ #include "sim_udp.h" +void sim_udp_t::udp_receive() { + // UDPSocket *udp = (UDPSocket *)udp_ptr; + + printf(" [INFO]: UDP Rx thread started\n"); + + socklen_t len = sizeof(this->udp.rx_addr); + + printf("here\n"); + + // create performance counter + // struct timespec start, end; + + // clock_gettime(CLOCK_MONOTONIC, &start); + + while (1) { + // int n = recvfrom(udp->sockfd, (void *)rx_buffer, sizeof(float) * N_OBSERVATIONS, MSG_WAITALL, (struct sockaddr *)&udp->robot_addr, &len); + + // if (n == sizeof(float) * N_OBSERVATIONS) { + // for (int i = 0; i < N_OBSERVATIONS; i++) { + // udp->obs[i] = rx_buffer[i]; + // } + // } + // else { + // // sleep for 1ms + // usleep(1000); + // } + + + if (this->rx_enabled) { + socklen_t len = sizeof(this->udp.rx_addr); + int n = recvfrom(this->udp.sockfd, (void *)this->rx_fifo, 512, MSG_WAITALL, (struct sockaddr *)&this->udp.rx_addr, &len); + + if (n) { + printf(" [INFO]: UDP Rx from (%s, %d) with data size: %d\n", + inet_ntoa(this->udp.rx_addr.sin_addr), + ntohs(this->udp.rx_addr.sin_port), + n + ); + } + } + } + // // perfromance + // clock_gettime(CLOCK_MONOTONIC, &end); -void sim_udp_t::write_udp_tx() { - printf(" [INFO]: Writing UDP TX with DMA pointer: 0x%lx, DMA size: %d\n", tx_fifo, reg_tx_size); - printf("addr: %x, port: %x\n", reg_addr_ip, reg_addr_tx_port); - sendto(udp->sockfd, (uint8_t *)tx_fifo, reg_tx_size, 0, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)); -} -void sim_udp_t::create_udp_tx() { - udp = (UDPRx *)malloc(sizeof(UDPRx)); + // long seconds = end.tv_sec - start.tv_sec; + // long ns = end.tv_nsec - start.tv_nsec; + + // // Correct for rollover + // if (start.tv_nsec > end.tv_nsec) { + // --seconds; + // ns += 1000000000; + // } - memset(&udp->client_addr, 0, sizeof(udp->client_addr)); - memset(&udp->host_addr, 0, sizeof(udp->host_addr)); + // clock_gettime(CLOCK_MONOTONIC, &start); - // host ip - udp->host_addr.sin_family = AF_INET; - udp->host_addr.sin_addr.s_addr = htonl(reg_addr_ip); - udp->host_addr.sin_port = htons(reg_addr_tx_port); + // double freq = 1.0 / (seconds + ns / 1000000000.0); + // // printf("Frequency: %f\n", freq); + // } +} +void sim_udp_t::udp_create_socket() { // Create socket file descriptor - if ((udp->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if ((this->udp.sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf(" [ERROR]: socket creation failed\n"); } - // if (bind(udp->sockfd, (const struct sockaddr *)&udp->host_addr, sizeof(udp->host_addr)) < 0) { - // printf(" [ERROR]: bind failed\n"); + printf(" [INFO]: socket created\n"); +} + +void sim_udp_t::udp_enable_rx() { + if (bind(udp.sockfd, (const struct sockaddr *)&udp.rx_addr, sizeof(udp.rx_addr)) < 0) { + printf(" [ERROR]: bind failed\n"); + } + + std::thread t1(&sim_udp_t::udp_receive, this); + t1.detach(); + + // // Create a thread running the receive() function + // if(pthread_create(&this->udp.thread_id, NULL, this->udp_receive, (void *)this->udp) != 0) { + // perror("[ERROR]: Failed to create receive thread"); // } - // Create a thread running the receive() function + this->rx_enabled = 1; + + + printf(" [INFO]: Rx thread created, thread ID: %ld\n", (long)this->udp.thread_id); +} + +void sim_udp_t::udp_enable_tx() { - printf(" [INFO]: Tx thread created, thread ID: %ld\n", (long)udp->thread_id); + this->tx_enabled = 1; + printf(" [INFO]: Tx thread created, thread ID: %ld\n", (long)this->udp.thread_id); } +void sim_udp_t::udp_write() { + + if (!this->tx_enabled) { + return; + } + + printf(" [INFO]: UDP Tx to (%s, %d) with data size: %d\n", + inet_ntoa(this->udp.tx_addr.sin_addr), + ntohs(this->udp.tx_addr.sin_port), + this->reg_txsize + ); + + sendto( + this->udp.sockfd, + (uint8_t *)this->tx_fifo, this->reg_txsize, 0, + (const struct sockaddr *)&this->udp.tx_addr, sizeof(this->udp.tx_addr) + ); +} bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { + printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); if (addr >= 0x1000 || len > 4) return false; uint32_t r = 0; switch (addr) { - case UDP_IP: r = reg_addr_ip; break; - case UDP_RXPORT: r = reg_addr_rx_port; break; - case UDP_TXPORT: r = reg_addr_tx_port; break; - case UDP_RXSIZE: r = reg_rx_size; break; + case UDP_RXIP: r = this->udp.rx_addr.sin_addr.s_addr; break; + case UDP_TXIP: r = this->udp.tx_addr.sin_addr.s_addr; break; + case UDP_RXPORT: r = this->udp.rx_addr.sin_port; break; + case UDP_TXPORT: r = this->udp.tx_addr.sin_port; break; + case UDP_CTRL: r = this->reg_ctrl; break; + case UDP_STATUS: r = this->reg_status; break; + case UDP_RXSIZE: r = this->reg_rxsize; break; + case UDP_TXSIZE: r = this->reg_txsize; break; default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); @@ -51,7 +137,7 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { - printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); + printf("STORE -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, *(uint32_t *)bytes); if (addr >= 0x1000 || len > 4) return false; @@ -60,24 +146,44 @@ bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { return true; } switch (addr) { - case UDP_IP: reg_addr_ip = *((uint32_t *)bytes); return true; - case UDP_RXPORT: reg_addr_rx_port = *((uint16_t *)bytes); return true; - case UDP_TXPORT: reg_addr_tx_port = *((uint16_t *)bytes); return true; - case UDP_TXCTRL: - if (bytes[0] == 1) write_udp_tx(); - if (bytes[0] == 2) create_udp_tx(); + case UDP_RXIP: + this->udp.rx_addr.sin_addr.s_addr = *((uint32_t *)bytes); + return true; + case UDP_TXIP: + this->udp.tx_addr.sin_addr.s_addr = *((uint32_t *)bytes); + return true; + case UDP_RXPORT: + this->udp.rx_addr.sin_port = *((uint16_t *)bytes); return true; - case UDP_TXSIZE: reg_tx_size = *((uint32_t *)bytes); return true; + case UDP_TXPORT: + this->udp.tx_addr.sin_port = *((uint16_t *)bytes); + return true; + case UDP_CTRL: + if (bytes[0] & (1 << 0)) { + this->udp_create_socket(); + } + if (bytes[0] & (1 << 1)) { + this->udp_enable_rx(); + } + if (bytes[0] & (1 << 2)) { + this->udp_enable_tx(); + } + if (bytes[0] & (1 << 3)) { + this->udp_write(); + } + return true; + case UDP_TXSIZE: this->reg_txsize = *((uint32_t *)bytes); return true; default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } } void sim_udp_t::tick(reg_t UNUSED rtc_ticks) { - if (rx_fifo.size() >= 1) return; - int rc = canonical_terminal_t::read(); - if (rc < 0) return; - rx_fifo.push((uint8_t)rc); - update_interrupts(); + // if (rx_fifo.size() >= 1) return; + // int rc = canonical_terminal_t::read(); + // if (rc < 0) return; + // rx_fifo.push((uint8_t)rc); + // update_interrupts(); + } int SimUDP_parseFDT(const void *fdt, reg_t *address, diff --git a/src/sim_udp.h b/src/sim_udp.h index e3b4924..d98fb1f 100644 --- a/src/sim_udp.h +++ b/src/sim_udp.h @@ -14,19 +14,18 @@ #include #include #include -#include +#include -#define UDP_IP 0x00 -#define UDP_RXPORT 0x04 -#define UDP_TXPORT 0x08 -#define UDP_RXCTRL 0x0C -#define UDP_TXCTRL 0x10 -#define UDP_RXSTATUS 0x14 -#define UDP_TXSTATUS 0x18 -#define UDP_RXSIZE 0x1C -#define UDP_TXSIZE 0x20 +#define UDP_RXIP 0x00 +#define UDP_TXIP 0x04 +#define UDP_RXPORT 0x08 +#define UDP_TXPORT 0x0C +#define UDP_CTRL 0x10 +#define UDP_STATUS 0x14 +#define UDP_RXSIZE 0x18 +#define UDP_TXSIZE 0x1C #define UDP_RXFIFO 0x30 #define UDP_TXFIFO 0x130 @@ -34,15 +33,27 @@ typedef struct { int sockfd; pthread_t thread_id; - struct sockaddr_in client_addr; - struct sockaddr_in host_addr; -} UDPRx; + struct sockaddr_in tx_addr; + struct sockaddr_in rx_addr; +} UDPSocket; class sim_udp_t : public abstract_device_t { public: - sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) : - ie(0), ip(0), txctrl(0), rxctrl(0), div(0), interrupt_id(int_id), intctrl(intctrl) { + sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { + this->interrupt_id = int_id; + this->intctrl = intctrl; + + this->udp.rx_addr.sin_family = AF_INET; + this->udp.tx_addr.sin_family = AF_INET; + + this->reg_ctrl = 0; + this->reg_status = 0; + this->reg_rxsize = 0; + this->reg_txsize = 0; + this->rx_enabled = 0; + this->tx_enabled = 0; + } bool load(reg_t addr, size_t len, uint8_t* bytes) override; @@ -50,47 +61,49 @@ class sim_udp_t : public abstract_device_t { void tick(reg_t UNUSED rtc_ticks) override; private: - std::queue rx_fifo; + uint32_t reg_ctrl; + uint32_t reg_status; + uint32_t reg_rxsize; + uint32_t reg_txsize; + + // std::queue rx_fifo; + uint8_t rx_fifo[256]; + uint8_t tx_fifo[256]; uint32_t ie; uint32_t ip; - uint32_t txctrl; - uint32_t rxctrl; - - uint8_t tx_fifo[256]; - - uint32_t reg_rx_size; - uint32_t reg_tx_size; - uint32_t div; reg_t interrupt_id; abstract_interrupt_controller_t *intctrl; - uint32_t reg_addr_ip; - uint32_t reg_addr_rx_port; - uint32_t reg_addr_tx_port; - - UDPRx *udp; - - void write_udp_tx(); - void create_udp_tx(); - - uint32_t read_rxfifo() { - if (!rx_fifo.size()) return 0x80000000; - uint8_t r = rx_fifo.front(); - rx_fifo.pop(); - update_interrupts(); - return r; - } - - void update_interrupts() { - int cond = 0; - if ((ie) || - ((ie) && rx_fifo.size())) { - cond = 1; - } - intctrl->set_interrupt_level(interrupt_id, (cond) ? 1 : 0); - } + UDPSocket udp; + // UDPSocket *udp_rx; + + uint8_t rx_enabled; + uint8_t tx_enabled; + + void udp_create_socket(); + void udp_enable_rx(); + void udp_enable_tx(); + void udp_write(); + void udp_receive(); + + // uint32_t read_rxfifo() { + // if (!rx_fifo.size()) return 0x80000000; + // uint8_t r = rx_fifo.front(); + // rx_fifo.pop(); + // update_interrupts(); + // return r; + // } + + // void update_interrupts() { + // int cond = 0; + // if ((ie) || + // ((ie) && rx_fifo.size())) { + // cond = 1; + // } + // intctrl->set_interrupt_level(interrupt_id, (cond) ? 1 : 0); + // } }; #endif // _SIM_UDP_H From b3c18873d406768c1d420c9a1e7cd3d6689f3247 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Thu, 27 Jun 2024 11:19:02 -0700 Subject: [PATCH 04/11] ADD: add documentation on SimUDP --- sim_udp.md | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 sim_udp.md diff --git a/sim_udp.md b/sim_udp.md new file mode 100644 index 0000000..cfed4b1 --- /dev/null +++ b/sim_udp.md @@ -0,0 +1,83 @@ + +# Simulated User Datagram Protocol (SimUDP) + +The SimUDP peripheral provides a mean to transmit and receive datagrams through a UDP socket connection. + +## SimUDP Registers + +### USART RXIP Register + +Address offset: 0x00 +Reset value: 0x0100_007F + +`Bit 31:0` IP: The IP address to listen to, in network endianness (big-endian) + +### USART TXIP Register + +Address offset: 0x04 +Reset value: 0x0100_007F + +`Bit 31:0` IP: The IP address to send to, in network endianness (big-endian) + +### USART RXPORT Register + +Address offset: 0x08 +Reset value: 0x0000_0000 + +`Bit 15:0` PORT: The receive port in network endianness (big-endian) + +### USART TXPORT Register + +Address offset: 0x0C +Reset value: 0x0000_0000 + +`Bit 15:0` PORT: The transmit port in network endianness (big-endian) + +### USART CTRL Register + +Address offset: 0x10 +Reset value: 0x0000_0000 + +`Bit 0` INIT: Initialize the socket object. Writing 1 to this bit creates a new socket. + +`Bit 1` RXEN: Enable the reception functionality. + +`Bit 2` TXEN: Enable the transmission functionality. + +`Bit 3` ST: Start tranmission of a Datagram. Writing 1 to this bit starts the transmitsion of a Datagram. After transmission, this bit will be cleared by hardware. + +### USART STATUS Register + +Address offset: 0x14 +Reset value: 0x0000_0000 + +`Bit 15:0` MAXRXSIZE: Maximum number of bytes to receive. + +### USART RXSIZE Register + +Address offset: 0x18 +Reset value: 0x0000_0000 + +`Bit 15:0` SIZE: Number of bytes received. + +### USART TXSIZE Register + +Address offset: 0x1C +Reset value: 0x0000_0000 + +`Bit 15:0` SIZE: Number of bytes to transmit. + +### USART RXFIFO Register[0:255] + +Address offset: 0x30 +Reset value: 0x0000_0000 + +`Bit 31:0` DATA + +### USART TXSIZE Register[0:255] + +Address offset: 0x130 +Reset value: 0x0000_0000 + +`Bit 31:0` DATA + From a3fe5b6898c11b8caca84d362dfbd62f2833b66e Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Thu, 27 Jun 2024 11:24:05 -0700 Subject: [PATCH 05/11] Co-authored-by: Lux Zhang --- src/sim_udp.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index 09b94b3..3709248 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -38,6 +38,8 @@ void sim_udp_t::udp_receive() { ntohs(this->udp.rx_addr.sin_port), n ); + + this->reg_rxsize = n; } } } From e5548475acae0b21ad3dde519cd56d46464e519b Mon Sep 17 00:00:00 2001 From: Lux Date: Fri, 13 Sep 2024 16:09:38 -0700 Subject: [PATCH 06/11] FIX: initial commit to a cleaner udp implementation --- sim_udp.md | 51 +++++++++---- src/sim_udp.cc | 204 +++++++++++++++++++++++++------------------------ src/sim_udp.h | 68 ++++++++--------- 3 files changed, 170 insertions(+), 153 deletions(-) diff --git a/sim_udp.md b/sim_udp.md index cfed4b1..212f259 100644 --- a/sim_udp.md +++ b/sim_udp.md @@ -5,79 +5,100 @@ The SimUDP peripheral provides a mean to transmit and receive datagrams through ## SimUDP Registers -### USART RXIP Register +### UDP RXIP Register Address offset: 0x00 Reset value: 0x0100_007F `Bit 31:0` IP: The IP address to listen to, in network endianness (big-endian) -### USART TXIP Register +### UDP TXIP Register Address offset: 0x04 Reset value: 0x0100_007F `Bit 31:0` IP: The IP address to send to, in network endianness (big-endian) -### USART RXPORT Register +### UDP RXPORT Register Address offset: 0x08 Reset value: 0x0000_0000 `Bit 15:0` PORT: The receive port in network endianness (big-endian) -### USART TXPORT Register +### UDP TXPORT Register Address offset: 0x0C Reset value: 0x0000_0000 `Bit 15:0` PORT: The transmit port in network endianness (big-endian) -### USART CTRL Register +### UDP CTRL Register Address offset: 0x10 Reset value: 0x0000_0000 -`Bit 0` INIT: Initialize the socket object. Writing 1 to this bit creates a new socket. +`Bit 0` ENABLE: Enable the device. -`Bit 1` RXEN: Enable the reception functionality. +`Bit 1` RXEN: Enable the reception functionality for one frame. -`Bit 2` TXEN: Enable the transmission functionality. +`Bit 2` TXEN: Enable the transmission functionality for one frame. -`Bit 3` ST: Start tranmission of a Datagram. Writing 1 to this bit starts the transmitsion of a Datagram. After transmission, this bit will be cleared by hardware. - -### USART STATUS Register +### UDP STATUS Register Address offset: 0x14 Reset value: 0x0000_0000 `Bit 15:0` MAXRXSIZE: Maximum number of bytes to receive. -### USART RXSIZE Register +### UDP RXSIZE Register Address offset: 0x18 Reset value: 0x0000_0000 `Bit 15:0` SIZE: Number of bytes received. -### USART TXSIZE Register +### UDP TXSIZE Register Address offset: 0x1C Reset value: 0x0000_0000 `Bit 15:0` SIZE: Number of bytes to transmit. -### USART RXFIFO Register[0:255] +### UDP RXFIFO Register[0:255] Address offset: 0x30 Reset value: 0x0000_0000 `Bit 31:0` DATA -### USART TXSIZE Register[0:255] +### UDP TXSIZE Register[0:255] Address offset: 0x130 Reset value: 0x0000_0000 `Bit 31:0` DATA + +## Programming Model + +``` +void UDP_enable() { + regwrite32(rxip, rxip); + regwrite32(txip, txip); + regwrite32(rxport, rxport); + regwrite32(txport, txport); + regwrite32(ctrl, 0x01); // enables the device +} +``` +``` +void UDP_config_recv(size){ + regwrite32(rx_size, size); +} +``` +``` +void UDP_receive_frame(){ + regwrite32(ctrl, 0x01 << 1); // turns on the udp rx flag for a frame + while (!rx_status); // poll untile done +} +``` \ No newline at end of file diff --git a/src/sim_udp.cc b/src/sim_udp.cc index 3709248..d23b9ff 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -1,7 +1,33 @@ #include "sim_udp.h" +// constructor +sim_udp_t::sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { + this->interrupt_id = int_id; + this->intctrl = intctrl; + + this->udp.rx_addr.sin_family = AF_INET; + this->udp.tx_addr.sin_family = AF_INET; + + this->reg_ctrl = 0; + this->reg_status = 0; + this->reg_rxsize = 0; + this->reg_txsize = 0; + + this->enabled = 0; + this->rx_flag = 0; + this->tx_flag = 0; + + this->udp_create_socket(); + + std::thread rx_thread(&sim_udp_t::udp_receive, this); + std::thread tx_thread(&sim_udp_t::udp_send, this); + + rx_thread.detach(); + tx_thread.detach(); + +} + void sim_udp_t::udp_receive() { - // UDPSocket *udp = (UDPSocket *)udp_ptr; printf(" [INFO]: UDP Rx thread started\n"); @@ -9,59 +35,47 @@ void sim_udp_t::udp_receive() { printf("here\n"); - // create performance counter - // struct timespec start, end; - - // clock_gettime(CLOCK_MONOTONIC, &start); - while (1) { - // int n = recvfrom(udp->sockfd, (void *)rx_buffer, sizeof(float) * N_OBSERVATIONS, MSG_WAITALL, (struct sockaddr *)&udp->robot_addr, &len); - - // if (n == sizeof(float) * N_OBSERVATIONS) { - // for (int i = 0; i < N_OBSERVATIONS; i++) { - // udp->obs[i] = rx_buffer[i]; - // } - // } - // else { - // // sleep for 1ms - // usleep(1000); - // } - - - if (this->rx_enabled) { + if (this->rx_flag) { socklen_t len = sizeof(this->udp.rx_addr); - int n = recvfrom(this->udp.sockfd, (void *)this->rx_fifo, 512, MSG_WAITALL, (struct sockaddr *)&this->udp.rx_addr, &len); + int n = recvfrom(this->udp.sockfd, (void *)this->rx_buffer, this->reg_rxsize, MSG_WAITALL, (struct sockaddr *)&this->udp.rx_addr, &len); + for (int i = 0; i < this->reg_rxsize; i++) { + this->rx_fifo.push(this->rx_buffer[i]); + } + if (n) { printf(" [INFO]: UDP Rx from (%s, %d) with data size: %d\n", inet_ntoa(this->udp.rx_addr.sin_addr), ntohs(this->udp.rx_addr.sin_port), n - ); - + ); this->reg_rxsize = n; } } } - // // perfromance - // clock_gettime(CLOCK_MONOTONIC, &end); - - - // long seconds = end.tv_sec - start.tv_sec; - // long ns = end.tv_nsec - start.tv_nsec; - - // // Correct for rollover - // if (start.tv_nsec > end.tv_nsec) { - // --seconds; - // ns += 1000000000; - // } - - // clock_gettime(CLOCK_MONOTONIC, &start); +} - // double freq = 1.0 / (seconds + ns / 1000000000.0); +void sim_udp_t::udp_send() { + while (1) { + if (this->tx_flag) { + printf(" [INFO]: UDP Tx to (%s, %d) with data size: %d\n", + inet_ntoa(this->udp.tx_addr.sin_addr), + ntohs(this->udp.tx_addr.sin_port), + this->reg_txsize + ); + + sendto( + this->udp.sockfd, + (uint8_t *)this->tx_buffer, this->reg_txsize, 0, + (const struct sockaddr *)&this->udp.tx_addr, sizeof(this->udp.tx_addr) + ); - // // printf("Frequency: %f\n", freq); - // } + for (int i = 0; i < this->reg_txsize; i++) { + this->tx_fifo.pop(); + } + } + } } void sim_udp_t::udp_create_socket() { @@ -69,53 +83,23 @@ void sim_udp_t::udp_create_socket() { if ((this->udp.sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf(" [ERROR]: socket creation failed\n"); } - printf(" [INFO]: socket created\n"); } -void sim_udp_t::udp_enable_rx() { - if (bind(udp.sockfd, (const struct sockaddr *)&udp.rx_addr, sizeof(udp.rx_addr)) < 0) { +void sim_udp_t::udp_enable() { + this->enabled = 1; + if (bind(this->udp.sockfd, (const struct sockaddr *)&this->udp.rx_addr, sizeof(this->udp.rx_addr)) < 0) { printf(" [ERROR]: bind failed\n"); } - - std::thread t1(&sim_udp_t::udp_receive, this); - t1.detach(); - - // // Create a thread running the receive() function - // if(pthread_create(&this->udp.thread_id, NULL, this->udp_receive, (void *)this->udp) != 0) { - // perror("[ERROR]: Failed to create receive thread"); - // } - - this->rx_enabled = 1; - - - printf(" [INFO]: Rx thread created, thread ID: %ld\n", (long)this->udp.thread_id); + printf(" [INFO]: bind success\n"); } -void sim_udp_t::udp_enable_tx() { - - - this->tx_enabled = 1; - printf(" [INFO]: Tx thread created, thread ID: %ld\n", (long)this->udp.thread_id); +void sim_udp_t::udp_set_rx_flag() { + this->rx_flag = 1; } -void sim_udp_t::udp_write() { - - if (!this->tx_enabled) { - return; - } - - printf(" [INFO]: UDP Tx to (%s, %d) with data size: %d\n", - inet_ntoa(this->udp.tx_addr.sin_addr), - ntohs(this->udp.tx_addr.sin_port), - this->reg_txsize - ); - - sendto( - this->udp.sockfd, - (uint8_t *)this->tx_fifo, this->reg_txsize, 0, - (const struct sockaddr *)&this->udp.tx_addr, sizeof(this->udp.tx_addr) - ); +void sim_udp_t::udp_set_tx_flag() { + this->tx_flag = 1; } bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { @@ -123,58 +107,76 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { if (addr >= 0x1000 || len > 4) return false; uint32_t r = 0; switch (addr) { - case UDP_RXIP: r = this->udp.rx_addr.sin_addr.s_addr; break; - case UDP_TXIP: r = this->udp.tx_addr.sin_addr.s_addr; break; - case UDP_RXPORT: r = this->udp.rx_addr.sin_port; break; - case UDP_TXPORT: r = this->udp.tx_addr.sin_port; break; - case UDP_CTRL: r = this->reg_ctrl; break; - case UDP_STATUS: r = this->reg_status; break; - case UDP_RXSIZE: r = this->reg_rxsize; break; - case UDP_TXSIZE: r = this->reg_txsize; break; + case UDP_RXFIFO_DATA: + r = this->rx_fifo.front(); + this->rx_fifo_to_pop = r; + break; + case UDP_RXFIFO_VALID: + r = this->rx_fifo.size() > 0; + break; + case UDP_TXFIFO_READY: + r = 1; + break; default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); return true; } - bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { printf("STORE -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, *(uint32_t *)bytes); if (addr >= 0x1000 || len > 4) return false; - if (addr >= UDP_TXFIFO) { - tx_fifo[addr - UDP_TXFIFO] = bytes[0]; - return true; - } switch (addr) { case UDP_RXIP: this->udp.rx_addr.sin_addr.s_addr = *((uint32_t *)bytes); return true; + case UDP_TXIP: this->udp.tx_addr.sin_addr.s_addr = *((uint32_t *)bytes); return true; + case UDP_RXPORT: this->udp.rx_addr.sin_port = *((uint16_t *)bytes); return true; + case UDP_TXPORT: this->udp.tx_addr.sin_port = *((uint16_t *)bytes); return true; + case UDP_CTRL: if (bytes[0] & (1 << 0)) { - this->udp_create_socket(); + this->udp_enable(); } if (bytes[0] & (1 << 1)) { - this->udp_enable_rx(); + this->udp_set_rx_flag(); } if (bytes[0] & (1 << 2)) { - this->udp_enable_tx(); - } - if (bytes[0] & (1 << 3)) { - this->udp_write(); + this->udp_set_tx_flag(); } return true; - case UDP_TXSIZE: this->reg_txsize = *((uint32_t *)bytes); return true; + + case UDP_RXSIZE: + this->reg_rxsize = *((uint32_t *)bytes); + return true; + + case UDP_TXSIZE: + this->reg_txsize = *((uint32_t *)bytes); + return true; + + case UDP_RXFIFO_READY: + this->rx_fifo.pop(); + return true; + + case UDP_TXFIFO_DATA: + this->tx_fifo_to_push = bytes[0]; + return true; + + case UDP_TXFIFO_VALID: + this->tx_fifo.push(this->tx_fifo_to_push); + return true; + default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } } @@ -219,12 +221,12 @@ sim_udp_t* SimUDP_parseFromFDT(const void* fdt, const sim_t* sim, reg_t* base, s std::string SimUDP_generateDTS(const sim_t* sim) { std::stringstream s; s << std::hex - << " udp: udp@" << 0x10001000 << " {\n" + << " udp: udp@" << UDP_BASE << " {\n" " compatible = \"ucbbar,sim_udp\";\n" " interrupt-parent = <&PLIC>;\n" " interrupts = <" << std::dec << 2; - reg_t blkdevbs = 0x10001000; - reg_t blkdevsz = 0x1000; + reg_t blkdevbs = UDP_BASE; + reg_t blkdevsz = UDP_SIZE; s << std::hex << ">;\n" " reg = <0x" << (blkdevbs >> 32) << " 0x" << (blkdevbs & (uint32_t)-1) << " 0x" << (blkdevsz >> 32) << " 0x" << (blkdevsz & (uint32_t)-1) << ">;\n" diff --git a/src/sim_udp.h b/src/sim_udp.h index d98fb1f..7b900d1 100644 --- a/src/sim_udp.h +++ b/src/sim_udp.h @@ -16,18 +16,25 @@ #include #include +#define UDP_BASE 0x10001000 +#define UDP_SIZE 0x1000 + +#define UDP_RXIP 0x00 +#define UDP_TXIP 0x04 +#define UDP_RXPORT 0x08 +#define UDP_TXPORT 0x0C +#define UDP_CTRL 0x10 +#define UDP_STATUS 0x14 +#define UDP_RXSIZE 0x18 +#define UDP_TXSIZE 0x1C +#define UDP_RXFIFO_DATA 0x20 +#define UDP_RXFIFO_VALID 0x24 +#define UDP_RXFIFO_READY 0x28 -#define UDP_RXIP 0x00 -#define UDP_TXIP 0x04 -#define UDP_RXPORT 0x08 -#define UDP_TXPORT 0x0C -#define UDP_CTRL 0x10 -#define UDP_STATUS 0x14 -#define UDP_RXSIZE 0x18 -#define UDP_TXSIZE 0x1C -#define UDP_RXFIFO 0x30 -#define UDP_TXFIFO 0x130 +#define UDP_TXFIFO_DATA 0x30 +#define UDP_TXFIFO_VALID 0x34 +#define UDP_TXFIFO_READY 0x38 typedef struct { @@ -39,23 +46,8 @@ typedef struct { class sim_udp_t : public abstract_device_t { public: - sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { - this->interrupt_id = int_id; - this->intctrl = intctrl; - - this->udp.rx_addr.sin_family = AF_INET; - this->udp.tx_addr.sin_family = AF_INET; - - this->reg_ctrl = 0; - this->reg_status = 0; - this->reg_rxsize = 0; - this->reg_txsize = 0; - - this->rx_enabled = 0; - this->tx_enabled = 0; - - } + sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id); bool load(reg_t addr, size_t len, uint8_t* bytes) override; bool store(reg_t addr, size_t len, const uint8_t* bytes) override; void tick(reg_t UNUSED rtc_ticks) override; @@ -65,10 +57,12 @@ class sim_udp_t : public abstract_device_t { uint32_t reg_status; uint32_t reg_rxsize; uint32_t reg_txsize; - - // std::queue rx_fifo; - uint8_t rx_fifo[256]; - uint8_t tx_fifo[256]; + uint8_t rx_buffer[256]; + uint8_t tx_buffer[256]; + std::queue rx_fifo; + std::queue tx_fifo; + uint8_t rx_fifo_to_pop; + uint8_t tx_fifo_to_push; uint32_t ie; uint32_t ip; @@ -77,17 +71,17 @@ class sim_udp_t : public abstract_device_t { abstract_interrupt_controller_t *intctrl; UDPSocket udp; - // UDPSocket *udp_rx; - uint8_t rx_enabled; - uint8_t tx_enabled; + uint8_t enabled; + uint8_t rx_flag; + uint8_t tx_flag; void udp_create_socket(); - void udp_enable_rx(); - void udp_enable_tx(); - void udp_write(); + void udp_enable(); + void udp_set_rx_flag(); + void udp_set_tx_flag(); void udp_receive(); - + void udp_send(); // uint32_t read_rxfifo() { // if (!rx_fifo.size()) return 0x80000000; // uint8_t r = rx_fifo.front(); From 80da4842ca84505a20e8e574700f29fbacd52972 Mon Sep 17 00:00:00 2001 From: Lux Date: Fri, 13 Sep 2024 16:19:19 -0700 Subject: [PATCH 07/11] ADD: status registers, write to unset --- src/sim_udp.cc | 22 +++++++++++++++++++++- src/sim_udp.h | 21 +++++---------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index d23b9ff..ac74294 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -24,7 +24,9 @@ sim_udp_t::sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { rx_thread.detach(); tx_thread.detach(); - + + this->rx_status = 0x00; + this->tx_status = 0x00; } void sim_udp_t::udp_receive() { @@ -52,6 +54,8 @@ void sim_udp_t::udp_receive() { ); this->reg_rxsize = n; } + + this->rx_status = 0x01; } } } @@ -74,6 +78,8 @@ void sim_udp_t::udp_send() { for (int i = 0; i < this->reg_txsize; i++) { this->tx_fifo.pop(); } + + this->tx_status = 0x01; } } } @@ -117,6 +123,12 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { case UDP_TXFIFO_READY: r = 1; break; + case UDP_RX_STATUS: + r = this->rx_status; + break; + case UDP_TX_STATUS: + r = this->tx_status; + break; default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); @@ -176,6 +188,14 @@ bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { case UDP_TXFIFO_VALID: this->tx_fifo.push(this->tx_fifo_to_push); return true; + + case UDP_RX_STATUS: + this->rx_status = 0x00; + return true; + + case UDP_TX_STATUS: + this->tx_status = 0x00; + return true; default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } diff --git a/src/sim_udp.h b/src/sim_udp.h index 7b900d1..8cffb89 100644 --- a/src/sim_udp.h +++ b/src/sim_udp.h @@ -36,6 +36,9 @@ #define UDP_TXFIFO_VALID 0x34 #define UDP_TXFIFO_READY 0x38 +#define UDP_RX_STATUS 0x40 +#define UDP_TX_STATUS 0x42 + typedef struct { int sockfd; @@ -75,6 +78,8 @@ class sim_udp_t : public abstract_device_t { uint8_t enabled; uint8_t rx_flag; uint8_t tx_flag; + uint8_t rx_status; + uint8_t tx_status; void udp_create_socket(); void udp_enable(); @@ -82,22 +87,6 @@ class sim_udp_t : public abstract_device_t { void udp_set_tx_flag(); void udp_receive(); void udp_send(); - // uint32_t read_rxfifo() { - // if (!rx_fifo.size()) return 0x80000000; - // uint8_t r = rx_fifo.front(); - // rx_fifo.pop(); - // update_interrupts(); - // return r; - // } - - // void update_interrupts() { - // int cond = 0; - // if ((ie) || - // ((ie) && rx_fifo.size())) { - // cond = 1; - // } - // intctrl->set_interrupt_level(interrupt_id, (cond) ? 1 : 0); - // } }; #endif // _SIM_UDP_H From d1396a6a064d7790eda6bec4f74c9a749fc1c6eb Mon Sep 17 00:00:00 2001 From: Lux Date: Fri, 13 Sep 2024 17:00:25 -0700 Subject: [PATCH 08/11] FIX: cosmetics update --- sim_udp.md | 2 +- src/sim_udp.cc | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sim_udp.md b/sim_udp.md index 212f259..45d727c 100644 --- a/sim_udp.md +++ b/sim_udp.md @@ -92,7 +92,7 @@ void UDP_enable() { } ``` ``` -void UDP_config_recv(size){ +void UDP_config_recv_size(uint32_t size){ regwrite32(rx_size, size); } ``` diff --git a/src/sim_udp.cc b/src/sim_udp.cc index ac74294..72e7d4e 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -34,9 +34,7 @@ void sim_udp_t::udp_receive() { printf(" [INFO]: UDP Rx thread started\n"); socklen_t len = sizeof(this->udp.rx_addr); - - printf("here\n"); - + while (1) { if (this->rx_flag) { socklen_t len = sizeof(this->udp.rx_addr); @@ -61,6 +59,9 @@ void sim_udp_t::udp_receive() { } void sim_udp_t::udp_send() { + + printf(" [INFO]: UDP Tx thread started\n"); + while (1) { if (this->tx_flag) { printf(" [INFO]: UDP Tx to (%s, %d) with data size: %d\n", @@ -231,14 +232,14 @@ int SimUDP_parseFDT(const void *fdt, reg_t *address, // An FDT node for a device should encode, at minimum, the base address for the device sim_udp_t* SimUDP_parseFromFDT(const void* fdt, const sim_t* sim, reg_t* base, std::vector sargs) { if (SimUDP_parseFDT(fdt, base, "ucbbar,sim_udp") == 0) { - printf("Found SimUDP at %lx\n", *base); + printf("Found SimUDP at 0x%lx\n", *base); return new sim_udp_t(sim->get_intctrl(), 1); } else { return nullptr; } } -std::string SimUDP_generateDTS(const sim_t* sim) { +std::string SimUDP_generateDTS(const sim_t* sim, const std::vector& args) { std::stringstream s; s << std::hex << " udp: udp@" << UDP_BASE << " {\n" From 7491c1b19eeec4ef5f8fae0c2f6ccfaa4b316acb Mon Sep 17 00:00:00 2001 From: Lux Date: Fri, 13 Sep 2024 21:06:11 -0700 Subject: [PATCH 09/11] FIX: hello world works --- src/sim_udp.cc | 42 +++++++++++++++++++++++++++--------------- src/sim_udp.h | 11 +++++++---- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index 72e7d4e..3875e53 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -25,8 +25,8 @@ sim_udp_t::sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { rx_thread.detach(); tx_thread.detach(); - this->rx_status = 0x00; - this->tx_status = 0x00; + this->reg_rx_status = 0x00; + this->reg_tx_status = 0x00; } void sim_udp_t::udp_receive() { @@ -39,21 +39,25 @@ void sim_udp_t::udp_receive() { if (this->rx_flag) { socklen_t len = sizeof(this->udp.rx_addr); int n = recvfrom(this->udp.sockfd, (void *)this->rx_buffer, this->reg_rxsize, MSG_WAITALL, (struct sockaddr *)&this->udp.rx_addr, &len); - - for (int i = 0; i < this->reg_rxsize; i++) { - this->rx_fifo.push(this->rx_buffer[i]); - } if (n) { + rx_fifo_mutex.lock(); + for (int i = 0; i < this->reg_rxsize; i++) { + this->rx_fifo.push(this->rx_buffer[i]); + } + rx_fifo_mutex.unlock(); + printf(" [INFO]: UDP Rx from (%s, %d) with data size: %d\n", inet_ntoa(this->udp.rx_addr.sin_addr), ntohs(this->udp.rx_addr.sin_port), n ); + + printf("\n"); this->reg_rxsize = n; + this->reg_rx_status = 0x01; } - this->rx_status = 0x01; } } } @@ -80,7 +84,7 @@ void sim_udp_t::udp_send() { this->tx_fifo.pop(); } - this->tx_status = 0x01; + this->reg_tx_status = 0x01; } } } @@ -110,13 +114,13 @@ void sim_udp_t::udp_set_tx_flag() { } bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { - printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); if (addr >= 0x1000 || len > 4) return false; uint32_t r = 0; switch (addr) { case UDP_RXFIFO_DATA: + rx_fifo_mutex.lock(); r = this->rx_fifo.front(); - this->rx_fifo_to_pop = r; + rx_fifo_mutex.unlock(); break; case UDP_RXFIFO_VALID: r = this->rx_fifo.size() > 0; @@ -125,37 +129,43 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { r = 1; break; case UDP_RX_STATUS: - r = this->rx_status; + r = this->reg_rx_status; + // printf("UDP_RX_STATUS: %d\n", r); break; case UDP_TX_STATUS: - r = this->tx_status; + r = this->reg_tx_status; break; default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); + printf("LOAD -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, r); return true; } bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { - printf("STORE -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, *(uint32_t *)bytes); + // printf("STORE -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, *(uint32_t *)bytes); if (addr >= 0x1000 || len > 4) return false; switch (addr) { case UDP_RXIP: this->udp.rx_addr.sin_addr.s_addr = *((uint32_t *)bytes); + printf("UDP_RXIP: %s\n", inet_ntoa(this->udp.rx_addr.sin_addr)); return true; case UDP_TXIP: this->udp.tx_addr.sin_addr.s_addr = *((uint32_t *)bytes); + printf("UDP_TXIP: %s\n", inet_ntoa(this->udp.tx_addr.sin_addr)); return true; case UDP_RXPORT: this->udp.rx_addr.sin_port = *((uint16_t *)bytes); + printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); return true; case UDP_TXPORT: this->udp.tx_addr.sin_port = *((uint16_t *)bytes); + printf("UDP_TXPORT: %d\n", ntohs(this->udp.tx_addr.sin_port)); return true; case UDP_CTRL: @@ -179,7 +189,9 @@ bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { return true; case UDP_RXFIFO_READY: + rx_fifo_mutex.lock(); this->rx_fifo.pop(); + rx_fifo_mutex.unlock(); return true; case UDP_TXFIFO_DATA: @@ -191,11 +203,11 @@ bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { return true; case UDP_RX_STATUS: - this->rx_status = 0x00; + this->reg_rx_status = 0x00; return true; case UDP_TX_STATUS: - this->tx_status = 0x00; + this->reg_tx_status = 0x00; return true; default: printf("STORE -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); diff --git a/src/sim_udp.h b/src/sim_udp.h index 8cffb89..7dbba28 100644 --- a/src/sim_udp.h +++ b/src/sim_udp.h @@ -15,7 +15,7 @@ #include #include #include - +#include #define UDP_BASE 0x10001000 #define UDP_SIZE 0x1000 @@ -37,7 +37,7 @@ #define UDP_TXFIFO_READY 0x38 #define UDP_RX_STATUS 0x40 -#define UDP_TX_STATUS 0x42 +#define UDP_TX_STATUS 0x44 typedef struct { @@ -63,7 +63,9 @@ class sim_udp_t : public abstract_device_t { uint8_t rx_buffer[256]; uint8_t tx_buffer[256]; std::queue rx_fifo; + std::mutex rx_fifo_mutex; std::queue tx_fifo; + std::mutex tx_fifo_mutex; uint8_t rx_fifo_to_pop; uint8_t tx_fifo_to_push; @@ -75,11 +77,12 @@ class sim_udp_t : public abstract_device_t { UDPSocket udp; + uint8_t reg_rx_status; + uint8_t reg_tx_status; + uint8_t enabled; uint8_t rx_flag; uint8_t tx_flag; - uint8_t rx_status; - uint8_t tx_status; void udp_create_socket(); void udp_enable(); From 381ce22236b4645c674de03e99ab1029a07a66c0 Mon Sep 17 00:00:00 2001 From: Lux Date: Sat, 14 Sep 2024 00:25:33 -0700 Subject: [PATCH 10/11] FIXME: port migrates after recv --- src/sim_udp.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index 3875e53..4ee2dfa 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -38,15 +38,17 @@ void sim_udp_t::udp_receive() { while (1) { if (this->rx_flag) { socklen_t len = sizeof(this->udp.rx_addr); + printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); int n = recvfrom(this->udp.sockfd, (void *)this->rx_buffer, this->reg_rxsize, MSG_WAITALL, (struct sockaddr *)&this->udp.rx_addr, &len); - + printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); if (n) { rx_fifo_mutex.lock(); for (int i = 0; i < this->reg_rxsize; i++) { this->rx_fifo.push(this->rx_buffer[i]); } rx_fifo_mutex.unlock(); - + + printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); printf(" [INFO]: UDP Rx from (%s, %d) with data size: %d\n", inet_ntoa(this->udp.rx_addr.sin_addr), ntohs(this->udp.rx_addr.sin_port), @@ -56,8 +58,8 @@ void sim_udp_t::udp_receive() { printf("\n"); this->reg_rxsize = n; this->reg_rx_status = 0x01; + this->rx_flag = 0; } - } } } @@ -81,10 +83,13 @@ void sim_udp_t::udp_send() { ); for (int i = 0; i < this->reg_txsize; i++) { + printf("%c", this->tx_fifo.front()); this->tx_fifo.pop(); } + printf("\n"); this->reg_tx_status = 0x01; + this->tx_flag = 0; } } } @@ -138,7 +143,7 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); - printf("LOAD -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, r); + // printf("LOAD -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, r); return true; } @@ -166,6 +171,7 @@ bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { case UDP_TXPORT: this->udp.tx_addr.sin_port = *((uint16_t *)bytes); printf("UDP_TXPORT: %d\n", ntohs(this->udp.tx_addr.sin_port)); + printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); return true; case UDP_CTRL: From c5d976cae5fa2013432b2dbf4941b3e71c7d7a98 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 15 Sep 2024 17:44:59 -0700 Subject: [PATCH 11/11] ADD: add working functional udp --- src/sim_udp.cc | 142 +++++++++++++++++++++---------------------------- src/sim_udp.h | 26 ++++++--- 2 files changed, 80 insertions(+), 88 deletions(-) diff --git a/src/sim_udp.cc b/src/sim_udp.cc index 4ee2dfa..b78b0c0 100644 --- a/src/sim_udp.cc +++ b/src/sim_udp.cc @@ -17,10 +17,17 @@ sim_udp_t::sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { this->rx_flag = 0; this->tx_flag = 0; - this->udp_create_socket(); - - std::thread rx_thread(&sim_udp_t::udp_receive, this); - std::thread tx_thread(&sim_udp_t::udp_send, this); + + // Create socket file descriptor + this->udp.sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (this->udp.sockfd < 0) { + printf(" [ERROR]: socket creation failed\n"); + exit(1); + } + + std::thread rx_thread(&sim_udp_t::udp_receive_handler, this); + std::thread tx_thread(&sim_udp_t::udp_send_handler, this); rx_thread.detach(); tx_thread.detach(); @@ -29,113 +36,103 @@ sim_udp_t::sim_udp_t(abstract_interrupt_controller_t *intctrl, reg_t int_id) { this->reg_tx_status = 0x00; } -void sim_udp_t::udp_receive() { - +void sim_udp_t::udp_receive_handler() { printf(" [INFO]: UDP Rx thread started\n"); - socklen_t len = sizeof(this->udp.rx_addr); - while (1) { if (this->rx_flag) { - socklen_t len = sizeof(this->udp.rx_addr); - printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); - int n = recvfrom(this->udp.sockfd, (void *)this->rx_buffer, this->reg_rxsize, MSG_WAITALL, (struct sockaddr *)&this->udp.rx_addr, &len); - printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); + int n = recvfrom(this->udp.sockfd, (void *)this->rx_buffer, this->reg_rxsize, MSG_WAITALL, NULL, 0); + if (n) { rx_fifo_mutex.lock(); - for (int i = 0; i < this->reg_rxsize; i++) { + for (int i = 0; i < n; i += 1) { this->rx_fifo.push(this->rx_buffer[i]); } rx_fifo_mutex.unlock(); - printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); - printf(" [INFO]: UDP Rx from (%s, %d) with data size: %d\n", - inet_ntoa(this->udp.rx_addr.sin_addr), - ntohs(this->udp.rx_addr.sin_port), - n - ); - - printf("\n"); this->reg_rxsize = n; this->reg_rx_status = 0x01; + this->rx_flag = 0; } } } } -void sim_udp_t::udp_send() { +void sim_udp_t::udp_send_handler() { printf(" [INFO]: UDP Tx thread started\n"); while (1) { - if (this->tx_flag) { + if (this->tx_flag && this->tx_fifo.size() >= this->reg_txsize) { printf(" [INFO]: UDP Tx to (%s, %d) with data size: %d\n", - inet_ntoa(this->udp.tx_addr.sin_addr), - ntohs(this->udp.tx_addr.sin_port), - this->reg_txsize + inet_ntoa(this->udp.tx_addr.sin_addr), + ntohs(this->udp.tx_addr.sin_port), + this->reg_txsize ); - + + for (int i = 0; i < this->reg_txsize; i += 1) { + this->tx_buffer[i] = this->tx_fifo.front(); + this->tx_fifo.pop(); + } + sendto( this->udp.sockfd, (uint8_t *)this->tx_buffer, this->reg_txsize, 0, (const struct sockaddr *)&this->udp.tx_addr, sizeof(this->udp.tx_addr) ); - for (int i = 0; i < this->reg_txsize; i++) { - printf("%c", this->tx_fifo.front()); - this->tx_fifo.pop(); - } - printf("\n"); - this->reg_tx_status = 0x01; this->tx_flag = 0; } } } -void sim_udp_t::udp_create_socket() { - // Create socket file descriptor - if ((this->udp.sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - printf(" [ERROR]: socket creation failed\n"); +void sim_udp_t::udp_enable() { + if (this->enabled) { + return; } - printf(" [INFO]: socket created\n"); -} -void sim_udp_t::udp_enable() { - this->enabled = 1; - if (bind(this->udp.sockfd, (const struct sockaddr *)&this->udp.rx_addr, sizeof(this->udp.rx_addr)) < 0) { + ssize_t status = bind(this->udp.sockfd, (const struct sockaddr *)&this->udp.rx_addr, sizeof(this->udp.rx_addr)); + if (status < 0) { printf(" [ERROR]: bind failed\n"); } printf(" [INFO]: bind success\n"); -} - -void sim_udp_t::udp_set_rx_flag() { - this->rx_flag = 1; -} + this->enabled = 1; -void sim_udp_t::udp_set_tx_flag() { - this->tx_flag = 1; } bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { + // if illegal address or length, return false if (addr >= 0x1000 || len > 4) return false; + uint32_t r = 0; switch (addr) { case UDP_RXFIFO_DATA: - rx_fifo_mutex.lock(); - r = this->rx_fifo.front(); - rx_fifo_mutex.unlock(); + if (this->rx_fifo.size() == 0) { + // set empty flag + r = 0x80000000; + } + else { + r = this->rx_fifo.front(); + this->rx_fifo.pop(); + } break; - case UDP_RXFIFO_VALID: - r = this->rx_fifo.size() > 0; + + case UDP_RXFIFO_SIZE: + r = this->rx_fifo.size(); break; - case UDP_TXFIFO_READY: - r = 1; + + case UDP_TXFIFO_DATA: + r = (this->tx_fifo.size() == FIFO_SIZE ? 0x80000000 : 0x00) | this->tx_fifo.back(); break; + + case UDP_TXFIFO_SIZE: + r = this->tx_fifo.size(); + break; + case UDP_RX_STATUS: r = this->reg_rx_status; - // printf("UDP_RX_STATUS: %d\n", r); break; case UDP_TX_STATUS: r = this->reg_tx_status; @@ -143,46 +140,39 @@ bool sim_udp_t::load(reg_t addr, size_t len, uint8_t* bytes) { default: printf("LOAD -- ADDR=0x%lx LEN=%lu\n", addr, len); abort(); } memcpy(bytes, &r, len); - // printf("LOAD -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, r); return true; } bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { - // printf("STORE -- ADDR=0x%lx LEN=%lu DATA=%lx\n", addr, len, *(uint32_t *)bytes); - + // if illegal address or length, return false if (addr >= 0x1000 || len > 4) return false; switch (addr) { case UDP_RXIP: this->udp.rx_addr.sin_addr.s_addr = *((uint32_t *)bytes); - printf("UDP_RXIP: %s\n", inet_ntoa(this->udp.rx_addr.sin_addr)); return true; case UDP_TXIP: this->udp.tx_addr.sin_addr.s_addr = *((uint32_t *)bytes); - printf("UDP_TXIP: %s\n", inet_ntoa(this->udp.tx_addr.sin_addr)); return true; case UDP_RXPORT: this->udp.rx_addr.sin_port = *((uint16_t *)bytes); - printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); return true; case UDP_TXPORT: this->udp.tx_addr.sin_port = *((uint16_t *)bytes); - printf("UDP_TXPORT: %d\n", ntohs(this->udp.tx_addr.sin_port)); - printf("UDP_RXPORT: %d\n", ntohs(this->udp.rx_addr.sin_port)); return true; case UDP_CTRL: - if (bytes[0] & (1 << 0)) { + if (READ_BITS(bytes[0], (1 << 0))) { this->udp_enable(); } - if (bytes[0] & (1 << 1)) { - this->udp_set_rx_flag(); + if (READ_BITS(bytes[0], (1 << 1))) { + this->rx_flag = 1; } - if (bytes[0] & (1 << 2)) { - this->udp_set_tx_flag(); + if (READ_BITS(bytes[0], (1 << 2))) { + this->tx_flag = 1; } return true; @@ -194,18 +184,8 @@ bool sim_udp_t::store(reg_t addr, size_t len, const uint8_t* bytes) { this->reg_txsize = *((uint32_t *)bytes); return true; - case UDP_RXFIFO_READY: - rx_fifo_mutex.lock(); - this->rx_fifo.pop(); - rx_fifo_mutex.unlock(); - return true; - case UDP_TXFIFO_DATA: - this->tx_fifo_to_push = bytes[0]; - return true; - - case UDP_TXFIFO_VALID: - this->tx_fifo.push(this->tx_fifo_to_push); + this->tx_fifo.push(bytes[0]); return true; case UDP_RX_STATUS: diff --git a/src/sim_udp.h b/src/sim_udp.h index 7dbba28..f2ec9e3 100644 --- a/src/sim_udp.h +++ b/src/sim_udp.h @@ -16,6 +16,16 @@ #include #include #include + + +/* ================ Bit Operation definitions ================ */ +#define SET_BITS(REG, BIT) ((REG) |= (BIT)) +#define CLEAR_BITS(REG, BIT) ((REG) &= ~(BIT)) +#define READ_BITS(REG, BIT) ((REG) & (BIT)) +#define WRITE_BITS(REG, CLEARMASK, SETMASK) ((REG) = (((REG) & (~(CLEARMASK))) | (SETMASK))) + + + #define UDP_BASE 0x10001000 #define UDP_SIZE 0x1000 @@ -29,17 +39,20 @@ #define UDP_TXSIZE 0x1C #define UDP_RXFIFO_DATA 0x20 -#define UDP_RXFIFO_VALID 0x24 +#define UDP_RXFIFO_SIZE 0x24 #define UDP_RXFIFO_READY 0x28 #define UDP_TXFIFO_DATA 0x30 -#define UDP_TXFIFO_VALID 0x34 +#define UDP_TXFIFO_SIZE 0x34 #define UDP_TXFIFO_READY 0x38 #define UDP_RX_STATUS 0x40 #define UDP_TX_STATUS 0x44 +#define FIFO_SIZE 16 + + typedef struct { int sockfd; pthread_t thread_id; @@ -60,8 +73,8 @@ class sim_udp_t : public abstract_device_t { uint32_t reg_status; uint32_t reg_rxsize; uint32_t reg_txsize; - uint8_t rx_buffer[256]; - uint8_t tx_buffer[256]; + uint8_t rx_buffer[FIFO_SIZE]; + uint8_t tx_buffer[FIFO_SIZE]; std::queue rx_fifo; std::mutex rx_fifo_mutex; std::queue tx_fifo; @@ -84,12 +97,11 @@ class sim_udp_t : public abstract_device_t { uint8_t rx_flag; uint8_t tx_flag; - void udp_create_socket(); void udp_enable(); void udp_set_rx_flag(); void udp_set_tx_flag(); - void udp_receive(); - void udp_send(); + void udp_receive_handler(); + void udp_send_handler(); }; #endif // _SIM_UDP_H