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

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sim/] [verilated/] [pipecmdr.h] - Blame information for rev 58

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 58 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    pipecmdr.h
4
//
5
// Project:     XuLA2-LX25 SoC based upon the ZipCPU
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 TCP/IP pipe
10
//      interface designed to act like a UART.  Indeed, the final interface has
11
//      often been a UART, although it is a JTAG-User command on the XULA board.
12
//      Still, this provides simple test facility designed to verify that the 
13
//      IP core in question works prior to such actual hardware implementation,
14
//      or alternatively to help debug a core after hardware implementation.
15
//
16
// Creator:     Dan Gisselquist, Ph.D.
17
//              Gisselquist Technology, LLC
18
//
19
////////////////////////////////////////////////////////////////////////////////
20
//
21
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
22
//
23
// This program is free software (firmware): you can redistribute it and/or
24
// modify it under the terms of  the GNU General Public License as published
25
// by the Free Software Foundation, either version 3 of the License, or (at
26
// your option) any later version.
27
//
28
// This program is distributed in the hope that it will be useful, but WITHOUT
29
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
30
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
31
// for more details.
32
//
33
// You should have received a copy of the GNU General Public License along
34
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
35
// target there if the PDF file isn't present.)  If not, see
36
// <http://www.gnu.org/licenses/> for a copy.
37
//
38
// License:     GPL, v3, as defined and found on www.gnu.org,
39
//              http://www.gnu.org/licenses/gpl.html
40
//
41
//
42
////////////////////////////////////////////////////////////////////////////////
43
//
44
//
45
#ifndef PIPECMDR_H
46
#define PIPECMDR_H
47
 
48
#include <sys/types.h>
49
#include <sys/socket.h>
50
#include <poll.h>
51
#include <unistd.h>
52
#include <arpa/inet.h>
53
 
54
#include "testb.h"
55
 
56
#define PIPEBUFLEN      256
57
 
58
//
59
// UARTLEN (a macro)
60
//
61
// Attempt to approximate our responses to the number of ticks a UART command
62
// would respond.
63
//
64
// At 115200 Baud, 8 bits of data, no parity and one stop bit, there will
65
// bit ten bits per character and therefore 8681 clocks per transfer
66
//      8681 ~= 100 MHz / 115200 (bauds / second) * 10 bauds / character
67
//
68
// #define      UARTLEN         8681 // Minimum ticks per character, 115200 Baud
69
//
70
// At 4MBaud, each bit takes 25 clocks.  10 bits would thus take 250 clocks
71
//              
72
#define UARTLEN         732     // Ticks per character: 1MBaud, 81.25MHz clock
73
 
74
template <class VA>     class   PIPECMDR : public TESTB<VA> {
75
        bool    m_debug;
76
 
77
        void    setup_listener(const int port) {
78
                struct  sockaddr_in     my_addr;
79
 
80
                signal(SIGPIPE, SIG_IGN);
81
 
82
                if (m_debug) printf("Listening on port %d\n", port);
83
 
84
                m_skt = socket(AF_INET, SOCK_STREAM, 0);
85
                if (m_skt < 0) {
86
                        perror("Could not allocate socket: ");
87
                        exit(-1);
88
                }
89
 
90
                // Set the reuse address option
91
                {
92
                        int optv = 1, er;
93
                        er = setsockopt(m_skt, SOL_SOCKET, SO_REUSEADDR, &optv, sizeof(optv));
94
                        if (er != 0) {
95
                                perror("SockOpt Err:");
96
                                exit(-1);
97
                        }
98
                }
99
 
100
                memset(&my_addr, 0, sizeof(struct sockaddr_in)); // clear structure
101
                my_addr.sin_family = AF_INET;
102
                my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
103
                my_addr.sin_port = htons(port);
104
 
105
                if (bind(m_skt, (struct sockaddr *)&my_addr, sizeof(my_addr))!=0) {
106
                        perror("BIND FAILED:");
107
                        exit(-1);
108
                }
109
 
110
                if (listen(m_skt, 1) != 0) {
111
                        perror("Listen failed:");
112
                        exit(-1);
113
                }
114
        }
115
 
116
public:
117
        int     m_skt, m_con;
118
        char    m_txbuf[PIPEBUFLEN], m_rxbuf[PIPEBUFLEN];
119
        int     m_ilen, m_rxpos, m_txpos, m_uart_wait, m_tx_busy;
120
        bool    m_started_flag;
121
        bool    m_copy;
122
 
123
        PIPECMDR(const int port, const bool copy_to_stdout=true)
124
                        : TESTB<VA>(), m_copy(copy_to_stdout) {
125
                m_debug = false;
126
                m_con = m_skt = -1;
127
                setup_listener(port);
128
                m_rxpos = m_txpos = m_ilen = 0;
129
                m_started_flag = false;
130
                m_uart_wait = 0; // Flow control into the FPGA
131
                m_tx_busy   = 0; // Flow control out of the FPGA
132
        }
133
 
134
        virtual void    kill(void) {
135
                // Close any active connection
136
                if (m_con >= 0)  close(m_con);
137
                if (m_skt >= 0) close(m_skt);
138
        }
139
 
140
        virtual void    tick(void) {
141
                if (m_con < 0) {
142
                        // Can we accept a connection?
143
                        struct  pollfd  pb;
144
 
145
                        pb.fd = m_skt;
146
                        pb.events = POLLIN;
147
                        poll(&pb, 1, 0);
148
 
149
                        if (pb.revents & POLLIN) {
150
                                m_con = accept(m_skt, 0, 0);
151
 
152
                                if (m_con < 0)
153
                                        perror("Accept failed:");
154
                        }
155
                }
156
 
157
                TESTB<VA>::m_core->i_rx_stb = 0;
158
 
159
                if (m_uart_wait == 0) {
160
                        if (m_ilen > 0) {
161
                                // Is there a byte in our buffer somewhere?
162
                                TESTB<VA>::m_core->i_rx_stb = 1;
163
                                TESTB<VA>::m_core->i_rx_data = m_rxbuf[m_rxpos++];
164
                                m_ilen--;
165
                        } else if (m_con > 0) {
166
                                // Is there a byte to be read here?
167
                                struct  pollfd  pb;
168
                                pb.fd = m_con;
169
                                pb.events = POLLIN;
170
                                if (poll(&pb, 1, 0) < 0)
171
                                        perror("Polling error:");
172
                                if (pb.revents & POLLIN) {
173
                                        if ((m_ilen =recv(m_con, m_rxbuf, sizeof(m_rxbuf), MSG_DONTWAIT)) > 0) {
174
                                                m_rxbuf[m_ilen] = '\0';
175
                                                if (m_rxbuf[m_ilen-1] == '\n') {
176
                                                        m_rxbuf[m_ilen-1] = '\0';
177
                                                        if (m_copy)
178
                                                                printf("< \'%s\'\n", m_rxbuf);
179
                                                        m_rxbuf[m_ilen-1] = '\n';
180
                                                } else if (m_copy)
181
                                                        printf("< \'%s\'\n", m_rxbuf);
182
                                                TESTB<VA>::m_core->i_rx_stb = 1;
183
                                                TESTB<VA>::m_core->i_rx_data = m_rxbuf[0];
184
                                                m_rxpos = 1; m_ilen--;
185
                                                m_started_flag = true;
186
                                        } else if (m_ilen < 0) {
187
                                                // An error occurred, close the connection
188
                                                // This could also be the
189
                                                // indication of a simple
190
                                                // connection close, so we deal
191
                                                // with this quietly.
192
                                                // perror("Read error: ");
193
                                                // fprintf(stderr, "Closing connection\n");
194
                                                close(m_con);
195
                                                m_con = -1;
196
                                        } else { // the connection closed on us
197
                                                close(m_con);
198
                                                m_con = -1;
199
                                        }
200
                                }
201
                        } m_uart_wait = (TESTB<VA>::m_core->i_rx_stb)?UARTLEN:0;
202
                } else {
203
                        // Still working on transmitting a character
204
                        m_uart_wait = m_uart_wait - 1;
205
                }
206
 
207
                TESTB<VA>::tick();
208
 
209
                if (m_tx_busy == 0) {
210
                        if ((TESTB<VA>::m_core->o_tx_stb)&&(m_con > 0)) {
211
                                m_txbuf[m_txpos++] = TESTB<VA>::m_core->o_tx_data;
212
                                if ((TESTB<VA>::m_core->o_tx_data == '\n')||(m_txpos >= (int)sizeof(m_txbuf))) {
213
                                        int     snt = 0;
214
                                        snt = send(m_con, m_txbuf, m_txpos, 0);
215
                                        if (snt < 0) {
216
                                                close(m_con);
217
                                                m_con = -1;
218
                                                snt = 0;
219
                                        }
220
                                        m_txbuf[m_txpos] = '\0';
221
                                        if (m_copy) printf("> %s", m_txbuf);
222
                                        if (snt < m_txpos) {
223
                                                fprintf(stderr, "Only sent %d bytes of %d!\n",
224
                                                        snt, m_txpos);
225
                                        }
226
                                        m_txpos = 0;
227
                                }
228
                        }
229
                } else
230
                        m_tx_busy--;
231
 
232
                if ((TESTB<VA>::m_core->o_tx_stb)&&(TESTB<VA>::m_core->i_tx_busy==0))
233
                        m_tx_busy = UARTLEN;
234
                TESTB<VA>::m_core->i_tx_busy = (m_tx_busy != 0);
235
        }
236
};
237
 
238
#endif

powered by: WebSVN 2.1.0

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