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

Subversion Repositories wbuart32

[/] [wbuart32/] [trunk/] [bench/] [cpp/] [linetest.cpp] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    linetest.cpp
4
//
5
// Project:     wbuart32, a full featured UART with simulator
6
//
7
// Purpose:     To create a pass-through test of the receiver and transmitter
8
//              which can be exercised/proven via Verilator.
9
//
10
//      If you run this program with no arguments, it will run an automatic
11 5 dgisselq
//      test, returning "PASS" on success, or "FAIL" on failure as a last
12 2 dgisselq
//      output line--hence it should support automated testing.
13
//
14
//      If you run with a '-i' argument, the program will run interactively.
15
//      It will then be up to you to determine if it works (or not).  As
16
//      always, it may be killed with a control C.
17
//
18
// Creator:     Dan Gisselquist, Ph.D.
19
//              Gisselquist Technology, LLC
20
//
21
////////////////////////////////////////////////////////////////////////////////
22
//
23 26 dgisselq
// Copyright (C) 2015-2019, Gisselquist Technology, LLC
24 2 dgisselq
//
25
// This program is free software (firmware): you can redistribute it and/or
26
// modify it under the terms of  the GNU General Public License as published
27
// by the Free Software Foundation, either version 3 of the License, or (at
28
// your option) any later version.
29
//
30
// This program is distributed in the hope that it will be useful, but WITHOUT
31
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
32
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
33
// for more details.
34
//
35
// You should have received a copy of the GNU General Public License along
36
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
37
// target there if the PDF file isn't present.)  If not, see
38
// <http://www.gnu.org/licenses/> for a copy.
39
//
40
// License:     GPL, v3, as defined and found on www.gnu.org,
41
//              http://www.gnu.org/licenses/gpl.html
42
//
43
//
44
////////////////////////////////////////////////////////////////////////////////
45
//
46
//
47 18 dgisselq
#include <verilatedos.h>
48 2 dgisselq
#include <stdio.h>
49
#include <fcntl.h>
50
#include <unistd.h>
51
#include <string.h>
52
#include <time.h>
53
#include <sys/types.h>
54 5 dgisselq
#include <sys/wait.h>
55 2 dgisselq
#include <signal.h>
56
#include "verilated.h"
57
#include "Vlinetest.h"
58 5 dgisselq
#include "verilated_vcd_c.h"
59 2 dgisselq
#include "uartsim.h"
60
 
61
int     main(int argc, char **argv) {
62
        Verilated::commandArgs(argc, argv);
63
        Vlinetest       tb;
64
        UARTSIM         *uart;
65
        bool            run_interactively = false;
66
        int             port = 0;
67 15 dgisselq
        unsigned        setup = 868;
68 5 dgisselq
        char string[] = "This is a UART testing string\r\n";
69 2 dgisselq
 
70
        for(int argn=1; argn<argc; argn++) {
71
                if (argv[argn][0] == '-') for(int j=1; (j<1000)&&(argv[argn][j]); j++)
72
                switch(argv[argn][j]) {
73
                        case 'i':
74
                                run_interactively = true;
75
                                break;
76
                        case 'p':
77
                                port = atoi(argv[argn++]); j+= 4000;
78
                                run_interactively = true;
79
                                break;
80
                        case 's':
81 3 dgisselq
                                setup= strtoul(argv[++argn], NULL, 0); j+= 4000;
82 2 dgisselq
                                break;
83
                        default:
84
                                printf("Undefined option, -%c\n", argv[argn][j]);
85
                                break;
86
                }
87
        }
88
 
89
        tb.i_setup = setup;
90 5 dgisselq
        int baudclocks = setup & 0x0ffffff;
91
        tb.i_uart_rx = 1;
92 2 dgisselq
        if (run_interactively) {
93
                uart = new UARTSIM(port);
94
                uart->setup(tb.i_setup);
95
 
96
                while(1) {
97
 
98
                        tb.i_clk = 1;
99
                        tb.eval();
100
                        tb.i_clk = 0;
101
                        tb.eval();
102
 
103 5 dgisselq
                        tb.i_uart_rx = (*uart)(tb.o_uart_tx);
104 2 dgisselq
                }
105
 
106
        } else {
107
                int     childs_stdin[2], childs_stdout[2];
108
 
109
                if ((pipe(childs_stdin)!=0)||(pipe(childs_stdout) != 0)) {
110
                        fprintf(stderr, "ERR setting up child pipes\n");
111
                        perror("O/S ERR");
112
                        printf("TEST FAILURE\n");
113
                        exit(EXIT_FAILURE);
114
                }
115
 
116 5 dgisselq
                pid_t childs_pid = fork();
117 2 dgisselq
 
118 5 dgisselq
                if (childs_pid < 0) {
119 2 dgisselq
                        fprintf(stderr, "ERR setting up child process\n");
120
                        perror("O/S ERR");
121
                        printf("TEST FAILURE\n");
122
                        exit(EXIT_FAILURE);
123
                }
124
 
125 5 dgisselq
                if (childs_pid) {
126 2 dgisselq
                        int     nr=-2, nw;
127
 
128
                        // We are the parent
129
                        close(childs_stdin[ 0]); // Close the read end
130
                        close(childs_stdout[1]); // Close the write end
131
 
132
                        char test[256];
133
 
134
                        nw = write(childs_stdin[1], string, strlen(string));
135
                        if (nw == (int)strlen(string)) {
136
                                int     rpos = 0;
137
                                test[0] = '\0';
138
                                while((rpos<nw)
139
                                        &&(0<(nr=read(childs_stdout[0],
140
                                                &test[rpos], strlen(string)-rpos))))
141
                                        rpos += nr;
142
 
143
                                nr = rpos;
144
                                if (rpos > 0)
145
                                        test[rpos] = '\0';
146
                                printf("Successfully read %d characters: %s\n", nr, test);
147
                        }
148
 
149 5 dgisselq
                        int     status = 0, rv = -1;
150 2 dgisselq
 
151 5 dgisselq
                        // Give the child the oppoortunity to take another
152
                        // 60 seconds to finish closing itself
153
                        for(int waitcount=0; waitcount < 60; waitcount++) {
154
                                rv = waitpid(-1, &status, WNOHANG);
155
                                if (rv == childs_pid)
156
                                        break;
157
                                else if (rv < 0)
158
                                        break;
159
                                else // rv == 0
160
                                        sleep(1);
161
                        }
162
 
163
                        if (rv != childs_pid) {
164
                                kill(childs_pid, SIGTERM);
165
                                printf("WARNING: Child/simulator did not terminate normally\n");
166
                        }
167
 
168
                        if (WEXITSTATUS(status) != EXIT_SUCCESS) {
169
                                printf("WARNING: Child/simulator exit status does not indicate success\n");
170
                        }
171
 
172 2 dgisselq
                        if ((nr == nw)&&(nw == (int)strlen(string))
173 5 dgisselq
                                        &&(strcmp(test, string) == 0)) {
174
                                printf("PASS!\n");
175
                                exit(EXIT_SUCCESS);
176
                        } else {
177 2 dgisselq
                                printf("TEST FAILED\n");
178 5 dgisselq
                                exit(EXIT_FAILURE);
179
                        }
180 2 dgisselq
                } else {
181
                        close(childs_stdin[ 1]);
182
                        close(childs_stdout[0]);
183
                        close(STDIN_FILENO);
184
                        if (dup(childs_stdin[0]) < 0) {
185
                                fprintf(stderr, "ERR setting up child FD\n");
186
                                perror("O/S ERR");
187
                                exit(EXIT_FAILURE);
188
                        }
189
                        close(STDOUT_FILENO);
190
                        if (dup(childs_stdout[1]) < 0) {
191
                                fprintf(stderr, "ERR setting up child FD\n");
192
                                perror("O/S ERR");
193
                                exit(EXIT_FAILURE);
194
                        }
195
 
196
                        // UARTSIM(0) uses stdin and stdout for its FD's
197
                        uart = new UARTSIM(0);
198
                        uart->setup(tb.i_setup);
199
 
200
                        // Make sure we don't run longer than 4 seconds ...
201
                        time_t  start = time(NULL);
202
                        int     iterations_before_check = 2048;
203 5 dgisselq
                        unsigned        clocks = 0;
204 2 dgisselq
                        bool    done = false;
205
 
206 5 dgisselq
#define VCDTRACE
207
#ifdef  VCDTRACE
208
                        Verilated::traceEverOn(true);
209
                        VerilatedVcdC* tfp = new VerilatedVcdC;
210
                        tb.trace(tfp, 99);
211
                        tfp->open("linetest.vcd");
212
#define TRACE_POSEDGE   tfp->dump(10*clocks)
213
#define TRACE_NEGEDGE   tfp->dump(10*clocks+5)
214
#define TRACE_CLOSE     tfp->close()
215
#else
216
#define TRACE_POSEDGE   while(0)
217
#define TRACE_NEGEDGE   while(0)
218
#define TRACE_CLOSE     while(0)
219
#endif
220
 
221
                        for(int i=0; i<(baudclocks*24); i++) {
222 2 dgisselq
                                // Clear any initial break condition
223
                                tb.i_clk = 1;
224
                                tb.eval();
225
                                tb.i_clk = 0;
226
                                tb.eval();
227
 
228 5 dgisselq
                                tb.i_uart_rx = 1;
229 2 dgisselq
                        }
230
 
231 5 dgisselq
                        while(clocks < 2*(baudclocks*16)*strlen(string)) {
232 2 dgisselq
                                tb.i_clk = 1;
233
                                tb.eval();
234 5 dgisselq
                                TRACE_POSEDGE;
235 2 dgisselq
                                tb.i_clk = 0;
236
                                tb.eval();
237 5 dgisselq
                                TRACE_NEGEDGE;
238
                                clocks++;
239 2 dgisselq
 
240 5 dgisselq
                                tb.i_uart_rx = (*uart)(tb.o_uart_tx);
241 2 dgisselq
 
242 3 dgisselq
                                if (false) {
243 5 dgisselq
                                        /*
244 3 dgisselq
                                        static long counts = 0;
245
                                        static int lasti = 1, lasto = 1;
246
                                        bool    writeout = false;
247 2 dgisselq
 
248 3 dgisselq
                                        counts++;
249
                                        if (lasti != tb.i_uart) {
250
                                                writeout = true;
251
                                                lasti = tb.i_uart;
252
                                        } if (lasto != tb.o_uart) {
253
                                                writeout = true;
254
                                                lasto = tb.o_uart;
255
                                        }
256
 
257
                                        if (writeout) {
258
                                        fprintf(stderr, "%08lx : [%d -> %d] %02x:%02x (%02x/%d) %d,%d->%02x [%2d/%d/%08x]\n",
259
                                                counts, tb.i_uart, tb.o_uart,
260
                                                tb.v__DOT__head,
261
                                                tb.v__DOT__tail,
262
                                                tb.v__DOT__lineend,
263
                                                tb.v__DOT__run_tx,
264
                                                tb.v__DOT__tx_stb,
265
                                                tb.v__DOT__transmitter__DOT__r_busy,
266
                                                tb.v__DOT__tx_data & 0x0ff,
267
                                                tb.v__DOT__transmitter__DOT__state,
268
                                                tb.v__DOT__transmitter__DOT__zero_baud_counter,
269
                                                tb.v__DOT__transmitter__DOT__baud_counter);
270 5 dgisselq
                                        } */
271 3 dgisselq
                                }
272
 
273 2 dgisselq
                                if (iterations_before_check-- <= 0) {
274
                                        iterations_before_check = 2048;
275
                                        done = ((time(NULL)-start)>60);
276
                                        if (done)
277
                                        fprintf(stderr, "CHILD-TIMEOUT\n");
278
                                }
279
                        }
280 5 dgisselq
 
281
                        TRACE_CLOSE;
282
 
283
                        exit(EXIT_SUCCESS);
284
                }
285 2 dgisselq
        }
286
}

powered by: WebSVN 2.1.0

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