Project

General

Profile

[logo] 
 
Home
About/Contact
Major Tools
  Dinotrace
  Verilator
  Verilog-mode
  Verilog-Perl
Other Tools
  IPC::Locker
  Parallel::Forker
  Voneline
General Info
  Papers

allow-strings-in-option-file.patch

Third version of the proposal - Yves Mathieu, 10/23/2019 07:16 AM

Download (11 KB)

View differences:

src/V3Options.cpp
1236 1236
    fl = new FileLine(filename);
1237 1237

  
1238 1238
    // Split into argument list and process
1239
    // Note we don't respect quotes.  It seems most simulators dont.
1240
    // Woez those that expect it; we'll at least complain.
1241
    if (whole_file.find('\"') != string::npos) {
1242
        fl->v3error("Double quotes in -f files cause unspecified behavior.");
1243
    }
1239
    // Note we try to respect escaped char, double/simple quoted strings
1240
    // Other simulators dont respect a common syntax...
1244 1241

  
1245 1242
    // Strip off arguments and parse into words
1246 1243
    std::vector<string> args;
1247
    string::size_type startpos = 0;
1248
    while (startpos < whole_file.length()) {
1249
        while (isspace(whole_file[startpos])) ++startpos;
1250
        string::size_type endpos = startpos;
1251
        while (endpos < whole_file.length() && !isspace(whole_file[endpos])) ++endpos;
1252
        if (startpos != endpos) {
1253
            string arg (whole_file, startpos, endpos-startpos);
1254
            args.reserve(args.size()+1);
1255
            args.push_back(arg);
1256
        }
1257
        startpos = endpos;
1244
    string::size_type pos = 0;
1245

  
1246
    // parse file using a state machine, taking into account quoted strings and escaped chars
1247
    enum state {ST_SEARCH_OPTION,
1248
                ST_IN_OPTION,
1249
                ST_ESCAPED_CHAR,
1250
                ST_IN_QUOTED_STR,
1251
                ST_IN_DOUBLE_QUOTED_STR};
1252

  
1253
    state st = ST_SEARCH_OPTION;
1254
    state last_st;
1255
    string arg("");
1256
    while (pos < whole_file.length()) {
1257
       char curr_char = whole_file[pos];
1258
       switch (st) {
1259
           case ST_SEARCH_OPTION:  // Wait for non space char
1260
               if (!isspace(curr_char))
1261
                   st = ST_IN_OPTION;
1262
               else
1263
                   break;
1264

  
1265
           case ST_IN_OPTION:  // Get all chars up to a white space or a "="
1266
               if (isspace(curr_char)) {  // end of option
1267
                  if (!arg.empty()) {  // end of word
1268
                       args.reserve(args.size()+1);
1269
                       args.push_back(arg);
1270
                   }
1271
                   arg = "";
1272
                   st = ST_SEARCH_OPTION;
1273
                   break;
1274
               }
1275
               if (curr_char == '\\') {  // Escape char, we wait for next char
1276
                   last_st = st;  // memorize current state
1277
                   st = ST_ESCAPED_CHAR;
1278
                   break;
1279
               }
1280
               if (curr_char == '\'') {  // find begin of quoted string
1281
                    // Examine next char in order to decide between
1282
                    // a string or a base specifier for integer literal
1283
                    ++pos;
1284
                    if(pos <  whole_file.length()) curr_char = whole_file[pos];
1285
                    if(curr_char == '"') {  // string
1286
                       st = ST_IN_QUOTED_STR;
1287
                    } else {  // base specifier
1288
                       arg += '\'';
1289
                    }
1290
                    arg +=  curr_char;
1291
                    break;
1292
               }
1293
               if (curr_char == '"') {  // find begin of double quoted string
1294
                    // doesn't insert char
1295
                    st = ST_IN_DOUBLE_QUOTED_STR;
1296
                    break;
1297
               }
1298
               arg += curr_char;
1299
               break;
1300

  
1301
           case ST_IN_QUOTED_STR:  // just store all chars inside string
1302
               if (curr_char != '\'') {
1303
                  arg += curr_char;
1304
               } else {  // End of quoted string
1305
                  st = ST_IN_OPTION;
1306
               }
1307
               break;
1308

  
1309
           case ST_IN_DOUBLE_QUOTED_STR:  // takes into account escaped chars
1310
               if (curr_char != '"') {
1311
                  if (curr_char == '\\') {
1312
                     last_st = st;  // memorize current state
1313
                     st = ST_ESCAPED_CHAR;
1314
                  } else {
1315
                    arg += curr_char;
1316
                  }
1317
               } else {  // End of double quoted string
1318
                  st = ST_IN_OPTION;
1319
               }
1320
               break;
1321

  
1322
           case ST_ESCAPED_CHAR:  // Just add the escaped char
1323
               arg += curr_char;
1324
               st = last_st;  // and return to last state
1325
               break;
1326

  
1327
       }
1328
       ++pos;
1329
    }
1330
    if (!arg.empty()) {  // add last word
1331
        args.reserve(args.size()+1);
1332
        args.push_back(arg);
1258 1333
    }
1259 1334

  
1260 1335
    // Path
test_regress/t/t_flag_define.v
2 2
//
3 3
// This file ONLY is placed into the Public Domain, for any use,
4 4
// without warranty, 2014 by Wilson Snyder
5
//
6
// Special cases of "string parameters" :
7
// This table compares obtain results from big-3 simulators to Verilator
8
// expected behavior. Base specified integer literals are also included as
9
// string detection may impact results for such cases.
10
//
11
// | In the options file       | simulator 1 | simulator 2 | simulator 3 | verilator   |
12
// |----------------------- ---|-------------|-------------|-------------|-------------|
13
// | +define+C0='"AB CD"'      | AB CD       | UNSUPPORTED | AB CD       | AB CD       |
14
// | +define+C1=\"AB\ CD\"     | AB CD       | UNSUPPORTED | AB CD       | AB CD       |
15
// | +define+C2="\"AB CD\""    | AB CD       | AB CD       | UNSUPPORTED | AB CD       |
16
// | +define+C3="\"AB\ CD\""   | AB CD       | AB CD       | UNSUPPORTED | AB CD       |
17
// | +define+C4=32'h600D600D   | UNSUPPORTED | 32'h600D600D| 32'h600D600D| 32'h600D600D|
18
// | +define+C5=32\'h600D600D  | 32'h600D600D| UNSUPPORTED | UNSUPPORTED | 32'h600D600D|
19
// | +define+C6="32'h600D600D" | 32'h600D600D| 32'h600D600D| 32'h600D600D| 32'h600D600D|
5 20

  
6 21
`define STRINGIFY(x) `"x`"
7 22

  
......
55 70
      $write("%%Error: Missing define\n"); $stop;
56 71
`endif
57 72

  
73
`ifdef STRING1
74
      if (`STRING1 !== "New String") $stop;
75
`else
76
      $write("%%Error: Missing define\n"); $stop;
77
`endif
78

  
79
`ifdef STRING2
80
      if (`STRING2 !== "New String") $stop;
81
`else
82
      $write("%%Error: Missing define\n"); $stop;
83
`endif
84

  
85
`ifdef STRING3
86
      if (`STRING3 !== "New String") $stop;
87
`else
88
      $write("%%Error: Missing define\n"); $stop;
89
`endif
90

  
91
`ifdef LIT1
92
      if (`STRINGIFY(`LIT1) !== "32'h600D600D") $stop;
93
`else
94
      $write("%%Error: Missing define\n"); $stop;
95
`endif
96

  
97
`ifdef LIT2
98
      if (`STRINGIFY(`LIT2) !== "32'h600D600D") $stop;
99
`else
100
      $write("%%Error: Missing define\n"); $stop;
101
`endif
102

  
103
`ifdef LIT3
104
      if (`STRINGIFY(`LIT3) !== "32'h600D600D") $stop;
105
`else
106
      $write("%%Error: Missing define\n"); $stop;
107
`endif
108

  
58 109
      $write("*-* All Finished *-*\n");
59 110
      $finish;
60 111
   end
test_regress/t/t_flag_define.vc
5 5
+define+D5A=VALA+D5B=VALB
6 6
// Quotes do NOT escape the plus
7 7
//+define+D5A="VALA+D5B"+D5C
8
+define+STRING1="\"New String\""
9
+define+STRING2='"New String"'
10
+define+STRING3=\"New\ String\"
11
+define+LIT1=32'h600D600D
12
+define+LIT2=32\'h600D600D
13
+define+LIT3="32'h600D600D"
test_regress/t/t_flag_parameter.pl
11 11

  
12 12
compile(
13 13
    # It is not possible to put them into the options file
14
    v_flags2 => ['-Gstring1="\"New String\"" -pvalue+string2="\"New String\"" -f t/t_flag_parameter.vc'],
14
    v_flags2 => ['-f t/t_flag_parameter.vc'],
15 15
    );
16 16

  
17 17
execute(
test_regress/t/t_flag_parameter.v
2 2
//
3 3
// This file ONLY is placed into the Public Domain, for any use,
4 4
// without warranty, 2016 by Wilson Snyder
5
//
6
// Special cases of "string parameters" :
7
// This table compares obtain results from big-3 simulators to Verilator
8
// expected behavior. Base specified integer literals are also included as
9
// string detection may impact results for such cases.
10
//
11
// | Option/Param file   | simulator 1 | simulator 2 | simulator 3 | verilator   |
12
// |---------------------|-------------|-------------|-------------|-------------|
13
// | -gC0='"AB CD"'      | AB CD       | UNSUPPORTED | AB CD       | AB CD       |
14
// | -gC1=\"AB\ CD\"     | AB CD       | UNSUPPORTED | UNSUPPORTED | AB CD       |
15
// | -gC2="\"AB CD\""    | AB CD       | AB CD       | AB CD       | AB CD       |
16
// | -gC3="\"AB\ CD\""   | AB CD       | AB\\ CD     | AB CD       | AB CD       |
17
// | -gC4=32'h600D600D   | UNSUPPORTED | 32'h600D600D| 32'h600D600D| 32'h600D600D|
18
// | -gC5=32\'h600D600D  | 32'h600D600D| UNSUPPORTED | UNSUPPORTED | 32'h600D600D|
19
// | -gC6="32'h600D600D" | 32'h600D600D| 32'h600D600D| UNSUPPORTED | 32'h600D600D|
5 20

  
6 21
`define check(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: Wrong parameter value", `__FILE__,`__LINE__); $stop; end while(0);
7 22

  
8 23
module t;
9 24
   parameter string1 = "Original String";
10 25
   parameter string2 = "Original String";
26
   parameter string11 = "Original String";
27
   parameter string12 = "Original String";
28
   parameter string21 = "Original String";
29
   parameter string22 = "Original String";
11 30

  
12 31
   parameter real11 = 0.1;
13 32
   parameter real12 = 0.1;
......
24 43
   parameter int32 = 1;
25 44
   parameter int41 = 1;
26 45
   parameter int42 = 1;
46
   parameter int51 = 1;
47
   parameter int52 = 1;
48
   parameter int61 = 1;
49
   parameter int62 = 1;
27 50

  
28 51
   initial begin
29 52
      `check(string1,"New String");
30 53
      `check(string2,"New String");
54
      `check(string11,"New String");
55
      `check(string12,"New String");
56
      `check(string21,"New String");
57
      `check(string22,"New String");
31 58
      `check(real11,0.2);
32 59
      `check(real12,0.2);
33 60
      `check(real21,400);
......
42 69
      `check(int32,123);
43 70
      `check(int41,32'hdeadbeef);
44 71
      `check(int42,32'hdeadbeef);
72
      `check(int51,32'hdeadbeef);
73
      `check(int52,32'hdeadbeef);
74
      `check(int61,32'hdeadbeef);
75
      `check(int62,32'hdeadbeef);
45 76

  
46 77
      $write("*-* All Finished *-*\n");
47 78
      $finish;
test_regress/t/t_flag_parameter.vc
1
-Gstring1="\"New String\""
2
-pvalue+string2="\"New String\""
3
-Gstring11='"New String"'
4
-pvalue+string12='"New String"'
5
-Gstring21=\"New\ String\"
6
-pvalue+string22=\"New\ String\"
1 7
-Greal11=0.2
2 8
-pvalue+real12=0.2
3 9
-Greal21=4e2
......
12 18
-pvalue+int32=123
13 19
-Gint41=32'hdead_beef
14 20
-pvalue+int42=32'hdead_beef
21
-Gint51=32\'hdead_beef
22
-pvalue+int52=32\'hdead_beef
23
-Gint61="32'hdead_beef"
24
-pvalue+int62="32'hdead_beef"