OpenCores
URL https://opencores.org/ocsvn/xulalx25soc/xulalx25soc/trunk

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [bench/] [cpp/] [pipecmdr.h] - Blame information for rev 47

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 dgisselq
//
2
//
3
// Filename:    pipecmdr.h
4
//
5
// Project:     FPGA testbench utilities.
6
//
7
// Purpose:     This program attaches to a Verilated Verilog IP core.
8
//              It will not work apart from such a core.  Once attached,
9
//              it connects the simulated core to a controller via a
10
//              pipe interface designed to act like a UART.  Indeed, it
11
//              is hoped that the final interface would be via UART.  Until
12
//              that point, however, this is just a simple test facility
13
//              designed to verify that the  IP core works prior to such
14
//              actual hardware implementation.
15
//
16
// Creator:     Dan Gisselquist
17
//              Gisselquist Tecnology, LLC
18
//
19
// Copyright:   2015
20
//
21
//
22
#ifndef PIPECMDR_H
23
#define PIPECMDR_H
24
 
25
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <poll.h>
28
#include <unistd.h>
29
#include <arpa/inet.h>
30
 
31
#include "testb.h"
32
 
33
#define PIPEBUFLEN      256
34
 
35
// At 115200 Baud, 8 bits of data, no parity and one stop bit, there will
36
// bit ten bits per character and therefore 8681 clocks per transfer
37
//      8681 ~= 100 MHz / 115200 (bauds / second) * 10 bauds / character
38
//
39
// #define      UARTLEN         8681 // Minimum ticks per character, 115200 Baud
40
//
41
// At 4MBaud, each bit takes 25 clocks.  10 bits would thus take 250 clocks
42
//              
43 47 dgisselq
// #define      UARTLEN         250 // Minimum ticks per character, 4M Baud
44
// #define      UARTLEN         1000 // Minimum ticks per character, 1M Hz
45 4 dgisselq
// #define      UARTLEN         8 // Minimum ticks per character
46 47 dgisselq
#define UARTLEN         4096    //
47 4 dgisselq
 
48
template <class VA>     class   PIPECMDR : public TESTB<VA> {
49
        void    setup_listener(const int port) {
50
                struct  sockaddr_in     my_addr;
51
 
52
                printf("Listening on port %d\n", port);
53
 
54
                m_skt = socket(AF_INET, SOCK_STREAM, 0);
55
                if (m_skt < 0) {
56
                        perror("Could not allocate socket: ");
57
                        exit(-1);
58
                }
59
 
60
                // Set the reuse address option
61
                {
62
                        int optv = 1, er;
63
                        er = setsockopt(m_skt, SOL_SOCKET, SO_REUSEADDR, &optv, sizeof(optv));
64
                        if (er != 0) {
65
                                perror("SockOpt Err:");
66
                                exit(-1);
67
                        }
68
                }
69
 
70
                memset(&my_addr, 0, sizeof(struct sockaddr_in)); // clear structure
71
                my_addr.sin_family = AF_INET;
72
                my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
73
                my_addr.sin_port = htons(port);
74
 
75
                if (bind(m_skt, (struct sockaddr *)&my_addr, sizeof(my_addr))!=0) {
76
                        perror("BIND FAILED:");
77
                        exit(-1);
78
                }
79
 
80
                if (listen(m_skt, 1) != 0) {
81
                        perror("Listen failed:");
82
                        exit(-1);
83
                }
84
        }
85
 
86
public:
87
        int     m_skt, m_con;
88
        char    m_txbuf[PIPEBUFLEN], m_rxbuf[PIPEBUFLEN];
89 47 dgisselq
        int     m_ilen, m_rxpos, m_txpos, m_uart_wait, m_tx_busy;
90 4 dgisselq
        bool    m_started_flag;
91
 
92
        PIPECMDR(const int port) : TESTB<VA>() {
93
                m_con = m_skt = -1;
94
                setup_listener(port);
95
                m_rxpos = m_txpos = m_ilen = 0;
96
                m_started_flag = false;
97 47 dgisselq
                m_uart_wait = 0; // Flow control into the FPGA
98
                m_tx_busy   = 0; // Flow control out of the FPGA
99 4 dgisselq
        }
100
 
101
        virtual void    kill(void) {
102
                // Close any active connection
103
                if (m_con >= 0)  close(m_con);
104
                if (m_skt >= 0) close(m_skt);
105
        }
106
 
107
        virtual void    tick(void) {
108
                if (m_con < 0) {
109
                        // Can we accept a connection?
110
                        struct  pollfd  pb;
111
 
112
                        pb.fd = m_skt;
113
                        pb.events = POLLIN;
114
                        poll(&pb, 1, 0);
115
 
116
                        if (pb.revents & POLLIN) {
117
                                m_con = accept(m_skt, 0, 0);
118
 
119
                                if (m_con < 0)
120
                                        perror("Accept failed:");
121
                        }
122
                }
123
 
124
                TESTB<VA>::m_core->i_rx_stb = 0;
125
 
126
                if (m_uart_wait == 0) {
127
                        if (m_ilen > 0) {
128
                                // Is there a byte in our buffer somewhere?
129
                                TESTB<VA>::m_core->i_rx_stb = 1;
130
                                TESTB<VA>::m_core->i_rx_data = m_rxbuf[m_rxpos++];
131
                                m_ilen--;
132
                        } else if (m_con > 0) {
133
                                // Is there a byte to be read here?
134
                                struct  pollfd  pb;
135
                                pb.fd = m_con;
136
                                pb.events = POLLIN;
137
                                if (poll(&pb, 1, 0) < 0)
138
                                        perror("Polling error:");
139
                                if (pb.revents & POLLIN) {
140
                                        if ((m_ilen =recv(m_con, m_rxbuf, sizeof(m_rxbuf), MSG_DONTWAIT)) > 0) {
141
                                                m_rxbuf[m_ilen] = '\0';
142
                                                if (m_rxbuf[m_ilen-1] == '\n') {
143
                                                        m_rxbuf[m_ilen-1] = '\0';
144
                                                        printf("< \'%s\'\n", m_rxbuf);
145
                                                        m_rxbuf[m_ilen-1] = '\n';
146
                                                } else printf("< \'%s\'\n", m_rxbuf);
147
                                                TESTB<VA>::m_core->i_rx_stb = 1;
148
                                                TESTB<VA>::m_core->i_rx_data = m_rxbuf[0];
149
                                                m_rxpos = 1; m_ilen--;
150
                                                m_started_flag = true;
151
                                        } else if (m_ilen < 0) {
152
                                                // An error occurred, close the connection
153 37 dgisselq
                                                // This could also be the
154
                                                // indication of a simple
155
                                                // connection close, so we deal
156
                                                // with this quietly.
157
                                                // perror("Read error: ");
158
                                                // fprintf(stderr, "Closing connection\n");
159 4 dgisselq
                                                close(m_con);
160
                                                m_con = -1;
161
                                        } else { // the connection closed on us
162
                                                close(m_con);
163
                                                m_con = -1;
164
                                        }
165
                                }
166
                        } m_uart_wait = (TESTB<VA>::m_core->i_rx_stb)?UARTLEN:0;
167
                } else {
168
                        // Still working on transmitting a character
169
                        m_uart_wait = m_uart_wait - 1;
170
                }
171
 
172
                /*
173
                if (TESTB<VA>::m_core->i_rx_stb) {
174
                        putchar(TESTB<VA>::m_core->i_rx_data);
175
                        fflush(stdout);
176
                }
177
                */
178
                TESTB<VA>::tick();
179
 
180 47 dgisselq
                bool tx_accepted = false;
181
                if (m_tx_busy == 0) {
182
                        if ((TESTB<VA>::m_core->o_tx_stb)&&(m_con > 0)) {
183
                                m_txbuf[m_txpos++] = TESTB<VA>::m_core->o_tx_data;
184
                                tx_accepted = true;
185
                                if ((TESTB<VA>::m_core->o_tx_data == '\n')||(m_txpos >= sizeof(m_txbuf))) {
186
                                        int     snt = 0;
187
                                        snt = send(m_con, m_txbuf, m_txpos, 0);
188
 
189
                                        m_txbuf[m_txpos] = '\0';
190
                                        printf("> %s", m_txbuf);
191
                                        if (snt < m_txpos) {
192
                                                fprintf(stderr, "Only sent %d bytes!\n",
193
                                                        snt);
194
                                        }
195
                                        m_txpos = 0;
196 4 dgisselq
                                }
197
                        }
198 47 dgisselq
                } else
199
                        m_tx_busy--;
200
 
201
                if ((TESTB<VA>::m_core->o_tx_stb)&&(TESTB<VA>::m_core->i_tx_busy==0))
202
                        m_tx_busy = UARTLEN;
203
                TESTB<VA>::m_core->i_tx_busy = (m_tx_busy != 0);
204
 
205
                if (0) {
206
                        if ((m_tx_busy!=0)||(TESTB<VA>::m_core->i_tx_busy)
207
                                ||(TESTB<VA>::m_core->o_tx_stb)
208
                                ||(tx_accepted))
209
                                printf("%4d %d %d %02x %s\n",
210
                                        m_tx_busy,
211
                                        TESTB<VA>::m_core->i_tx_busy,
212
                                        TESTB<VA>::m_core->o_tx_stb,
213
                                        TESTB<VA>::m_core->o_tx_data,
214
                                        (tx_accepted)?"READ!":"");
215 4 dgisselq
                }
216
 
217 47 dgisselq
 
218 4 dgisselq
                /*
219
                if((TESTB<VA>::m_core->o_wb_cyc)||(TESTB<VA>::m_core->o_wb_stb)){
220
                        printf("BUS: %d,%d,%d %8x %8x\n",
221
                                TESTB<VA>::m_core->o_wb_cyc,
222
                                TESTB<VA>::m_core->o_wb_stb,
223
                                TESTB<VA>::m_core->o_wb_we,
224
                                TESTB<VA>::m_core->o_wb_addr,
225
                                TESTB<VA>::m_core->o_wb_data);
226
                } else if (m_started_flag) {
227
                        printf("%02x,%c,%d,%d,%02x -> %d,%d,%d, %2x,%2x,%2x\n",
228
                                TESTB<VA>::m_core->i_rx_data,
229
                                (TESTB<VA>::m_core->i_rx_stb)?(TESTB<VA>::m_core->i_rx_data):' ',
230
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__r_valid,
231
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__rx_eol,
232
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__rx_six_bits,
233
                                //
234
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__o_rq_strobe,
235
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__o_rq_hold,
236
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__o_rq_we,
237
                                //
238
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__state,
239
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__nreg,
240
                                TESTB<VA>::m_core->v__DOT__decodewb__DOT__szreg);
241
                }
242
                */
243
        }
244
};
245
 
246
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.