OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [perl_gui/] [lib/] [perl/] [compile.pl] - Blame information for rev 38

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

Line No. Rev Author Line
1 34 alirezamon
#! /usr/bin/perl -w
2
use Glib qw/TRUE FALSE/;
3
use strict;
4
use warnings;
5
use soc;
6
#use ip;
7
#use interface;
8
#use POSIX 'strtol';
9
 
10
use File::Path;
11
use File::Find::Rule;
12
use File::Copy;
13
use File::Copy::Recursive qw(dircopy);
14
use Cwd 'abs_path';
15
use Verilog::EditFiles;
16
 
17
use Gtk2;
18
#use Gtk2::Pango;
19
 
20
use List::MoreUtils qw( minmax );
21
 
22
 
23
 
24
################
25
#       Comile
26
#################
27
 
28
 
29
 
30
sub is_capital_sensitive()
31
{
32
  my ($cell_layout, $cell, $tree_model, $iter, $data) = @_;
33
  my $sensitive = !$tree_model->iter_has_child($iter);
34
  $cell->set('sensitive', $sensitive);
35
}
36
 
37
sub gen_combo_model{
38
        my $ref=shift;
39
        my %inputs=%{$ref};
40
        my $store = Gtk2::TreeStore->new('Glib::String');
41
         for my $i (sort { $a cmp $b} keys %inputs ) {
42
                my $iter = $store->append(undef);
43
 
44
                $store->set($iter, 0, $i);
45
                for my $capital (sort { $a cmp $b} keys %{$inputs{$i}}) {
46
                        my $iter2 = $store->append($iter);
47
                        $store->set($iter2, 0, $capital);
48
                }
49
        }
50
        return $store;
51
 
52
}
53
 
54
sub gen_tree_combo{
55
        my $model=shift;
56
        my $combo = Gtk2::ComboBox->new_with_model($model);
57
        my $renderer = Gtk2::CellRendererText->new();
58
        $combo->pack_start($renderer, TRUE);
59
        $combo->set_attributes($renderer, "text", 0);
60
        $combo->set_cell_data_func($renderer, \&is_capital_sensitive);
61
        return $combo;
62
 
63
}
64
 
65
sub get_range {
66
        my ($board,$self,$porttype,$assignname,$portrange,$portname) =@_;
67
        my $box= def_hbox(FALSE,0);
68
        my @range=$board->board_get_pin_range($porttype,$assignname);
69
 
70
 
71
        if ($range[0] ne '*undefine*'){
72
                my $content = join(",", @range);
73
                my ($min, $max) = minmax @range;
74
                if  (length($portrange)!=0){
75
                        my $range_hsb=gen_combobox_object($self,'compile_pin_range_hsb',$portname,$content,$max,undef,undef);
76
                        $box->pack_start( $range_hsb, FALSE, FALSE, 0);
77
                        $box->pack_start(gen_label_in_center(':'),, FALSE, FALSE, 0);
78
                }
79
 
80
                my $range_lsb=gen_combobox_object($self,'compile_pin_range_lsb',$portname,$content,$min,undef,undef);
81
                $box->pack_start( $range_lsb, FALSE, FALSE, 0);
82
 
83
        }
84
        return $box;
85
 
86
}
87
 
88
 
89 38 alirezamon
sub read_top_v_file{
90
        my $top_v=shift;
91 34 alirezamon
        my $board = soc->board_new();
92 38 alirezamon
        my $vdb=read_verilog_file($top_v);
93
        my @modules=sort $vdb->get_modules($top_v);
94
        my %Ptypes=get_ports_type($vdb,$modules[0]);
95
        my %Pranges=get_ports_rang($vdb,$modules[0]);
96
        foreach my $p (sort keys %Ptypes){
97
                my $Ptype=$Ptypes{$p};
98
                my $Prange=$Pranges{$p};
99
                my $type=($Ptype eq "input")? "Input" : ($Ptype eq "output")? 'Output' : 'Bidir';
100
                if (  $Prange ne ''){
101
                        my @r=split(":",$Prange);
102
                        my $a=($r[0]<$r[1])? $r[0] : $r[1];
103
                        my $b=($r[0]<$r[1])? $r[1] : $r[0];
104
                        for (my $i=$a; $i<=$b; $i++){
105
                                $board->board_add_pin ($type,"$p\[$i\]");
106
 
107
                        }
108 34 alirezamon
                }
109 38 alirezamon
                else {$board->board_add_pin ($type,$p);}
110
        }
111 34 alirezamon
        return $board;
112
}
113
 
114
 
115
 
116
 
117
sub gen_top_v{
118
        my ($self,$board,$name,$top)=@_;
119
 
120
        my $top_v=get_license_header("Top.v");
121
        #read port list 
122
        my $vdb=read_verilog_file($top);
123
        my %port_type=get_ports_type($vdb,"${name}_top");
124
        my %port_range=get_ports_rang($vdb,"${name}_top");
125
 
126
 
127
        my $io='';
128
        my $io_def='';
129
        my $io_assign='';
130
        my %board_io;
131
        my $first=1;
132
        foreach my $p (sort keys %port_type){
133
                my $porttype=$port_type{$p};
134
                my $portrange=$port_range{$p};
135
                my $assign_type = $self->object_get_attribute('compile_assign_type',$p);
136
                my $assign_name = $self->object_get_attribute('compile_pin',$p);
137
                my $range_hsb   = $self->object_get_attribute('compile_pin_range_hsb',$p);
138
                my $range_lsb   = $self->object_get_attribute('compile_pin_range_lsb',$p);
139
                my $assign="\t";
140
                if (defined $assign_name){
141
                        if($assign_name eq '*VCC'){
142
                                $assign= (length($portrange)!=0)? '{32{1\'b1}}' : '1\'b1';
143
                        } elsif ($assign_name eq '*GND'){
144
                                $assign= (length($portrange)!=0)? '{32{1\'b0}}' : '1\'b0';
145
                        }elsif ($assign_name eq '*NOCONNECT'){
146
                                $assign="\t";
147
 
148
                        }else{
149
 
150
                                $board_io{$assign_name}=$porttype;
151
 
152
 
153
                                my $range = (defined $range_hsb) ? "[$range_hsb : $range_lsb]" :
154
                                            (defined $range_lsb) ?  "[ $range_lsb]" : " ";
155
                                my $l=(defined $assign_type)?
156
                                        ($assign_type eq 'Direct') ? '' : '~' : '';
157
                                $assign="$l $assign_name $range";
158
 
159
 
160
                        }
161
                }
162
                $io_assign= ($first)? "$io_assign \t  .$p($assign)":"$io_assign,\n \t  .$p($assign)";
163
                $first=0;
164
        }
165
        $first=1;
166
        foreach my $p (sort keys %board_io){
167
                        $io=($first)? "\t$p" : "$io,\n\t$p";
168
                        my $dir=$board_io{$p};
169
                        my $range;
170
                        my $type= ($dir eq  'input') ? 'Input' :
171
                                  ($dir eq  'output')? 'Output' : 'Bidir';
172
                        my @r= $board->board_get_pin_range($type,$p);
173
                        if ($r[0] eq '*undefine*'){
174
                                $range="\t\t\t";
175
                        } else {
176
                                my ($min, $max) = minmax @r;
177
                                $range="\t[$max : $min]\t";
178
                        }
179
                        $io_def = "$io_def \t $dir $range $p;\n";
180
                        $first=0;
181
 
182
        }
183
        $top_v="$top_v
184
module Top (
185
$io
186
);
187
$io_def
188
 
189
        ${name}_top uut(
190
$io_assign
191
        );
192
 
193
 
194
endmodule
195
";
196
        my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
197
        my $board_top_file= "$fpath/Top.v";
198
        save_file($board_top_file,$top_v);
199
}
200
 
201
 
202
 
203
 
204
 
205
 
206
 
207
 
208
 
209
 
210
sub select_compiler {
211 38 alirezamon
        my ($self,$name,$top,$target_dir,$end_func)=@_;
212 34 alirezamon
        my $window = def_popwin_size(40,40,"Step 1: Select Compiler",'percent');
213
        #get the list of boards located in "boards/*" folder
214 38 alirezamon
        my @dirs = grep {-d} glob("../boards/*");
215 34 alirezamon
        my ($fpgas,$init);
216
        foreach my $dir (@dirs) {
217
                my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
218
                $init=$name;
219
                $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
220
        }
221
        my $table = def_table(2, 2, FALSE);
222
        my $col=0;
223
        my $row=0;
224
 
225 38 alirezamon
        my $compilers=$self->object_get_attribute('compile','compilers');#"QuartusII,Verilator,Modelsim"
226
 
227
        my $compiler=gen_combobox_object ($self,'compile','type',$compilers,"QuartusII",undef,undef);
228 34 alirezamon
        $table->attach(gen_label_in_center("Compiler tool"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
229
        $table->attach($compiler,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
230
        $row++;$col=0;
231
 
232
 
233
 
234
        my $old_board_name=$self->object_get_attribute('compile','board');
235
        my $old_compiler=$self->object_get_attribute('compile','type');
236
        my $compiler_options = ($old_compiler eq "QuartusII")? select_board  ($self,$name,$top,$target_dir):
237
                               ($old_compiler eq "Modelsim")?  select_model_path  ($self,$name,$top,$target_dir):
238
                                                                gen_label_in_center(" ");
239
        $table->attach($compiler_options,$col,$col+2,$row,$row+1,'fill','shrink',2,2); $row++;
240
 
241
        $col=1;
242
        my $i;
243
        for ($i=$row; $i<5; $i++){
244
 
245
                my $temp=gen_label_in_center(" ");
246
                $table->attach_defaults ($temp, 0, 1 , $i, $i+1);
247
        }
248
        $row=$i;
249
 
250
 
251
        $window->add ($table);
252
        $window->show_all();
253
        my $next=def_image_button('icons/right.png','Next');
254
        $table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++;
255
        $next-> signal_connect("clicked" => sub{
256
                my $compiler_type=$self->object_get_attribute('compile','type');
257
                if($compiler_type eq "QuartusII"){
258
                        my $new_board_name=$self->object_get_attribute('compile','board');
259
                        if(defined $old_board_name) {
260 38 alirezamon
                                if ($old_board_name ne $new_board_name){
261
                                        remove_pin_assignment($self);
262
                                        my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
263
                                        #delete jtag_intfc.sh file
264
                                        unlink "${fpath}../sw/jtag_intfc.sh";
265
                                        #program_device.sh file  
266
                                        unlink "${fpath}../program_device.sh";
267
                                }
268
 
269 34 alirezamon
                                my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
270
                                my $board_top_file= "$fpath/Top.v";
271
                                unlink $board_top_file if ($old_board_name ne $new_board_name);
272
 
273
 
274
                        }
275 38 alirezamon
                        if($new_board_name eq "Add New Board") {add_new_fpga_board($self,$name,$top,$target_dir,$end_func);}
276
                        else {get_pin_assignment($self,$name,$top,$target_dir,$end_func);}
277 34 alirezamon
                }elsif($compiler_type eq "Modelsim"){
278
                        modelsim_compilation($self,$name,$top,$target_dir);
279
 
280
                }else{#verilator
281 38 alirezamon
                        verilator_compilation_win($self,$name,$top,$target_dir);
282 34 alirezamon
 
283
                }
284
 
285
                $window->destroy;
286
 
287
        });
288
 
289
        $compiler->signal_connect("changed" => sub{
290
                $compiler_options->destroy;
291
                my $new_board_name=$self->object_get_attribute('compile','type');
292
                $compiler_options = ($new_board_name eq "QuartusII")? select_board  ($self,$name,$top,$target_dir):
293
                                    ($new_board_name eq "Modelsim")?  select_model_path  ($self,$name,$top,$target_dir):
294
                                 gen_label_in_center(" ");
295
                $table->attach($compiler_options,0,2,1,2,'fill','shrink',2,2);
296
                $table->show_all;
297
 
298
        });
299
 
300
}
301
 
302
 
303
 
304
 
305
 
306
sub select_board {
307
        my ($self,$name,$top,$target_dir)=@_;
308
 
309
        #get the list of boards located in "boards/*" folder
310 38 alirezamon
        my @dirs = grep {-d} glob("../boards/*");
311 34 alirezamon
        my ($fpgas,$init);
312 38 alirezamon
        $fpgas="Add New Board";
313
 
314 34 alirezamon
        foreach my $dir (@dirs) {
315
                my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
316 38 alirezamon
 
317
                $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
318
                $init="$name";
319 34 alirezamon
        }
320
        my $table = def_table(2, 2, FALSE);
321
        my $col=0;
322
        my $row=0;
323
 
324
 
325
        my $old_board_name=$self->object_get_attribute('compile','board');
326 38 alirezamon
        $table->attach(gen_label_help("The list of supported boards are obtained from \"mpsoc/boards/\" path. You can add your boards by adding its required files in aformentioned path. Note that currently only Altera FPGAs are supported. For boards from other vendors, you need to directly use their own compiler and call $name.v file in your top level module.",'Targeted Board:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
327 34 alirezamon
        $table->attach(gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
328
 
329
        my $bin = $self->object_get_attribute('compile','quartus_bin');
330
        my $Quartus_bin=  $ENV{QUARTUS_BIN};
331
        $col=0;
332
        $self->object_add_attribute('compile','quartus_bin',$ENV{QUARTUS_BIN}) if (!defined $bin && defined $Quartus_bin);
333
        $table->attach(gen_label_help("Path to quartus/bin directory. You can set a default path as QUARTUS_BIN envirement variable in ~/.bashrc file.
334
e.g:  export QUARTUS_BIN=/home/alireza/altera/13.0sp1/quartus/bin",'Quartus  bin:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
335
        $table->attach(get_dir_in_object ($self,'compile','quartus_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
336
 
337
        return $table;
338
 
339
}
340
 
341
sub select_model_path {
342
        my ($self,$name,$top,$target_dir)=@_;
343
 
344
 
345
        my $table = def_table(2, 2, FALSE);
346
        my $col=0;
347
        my $row=0;
348
 
349
 
350
 
351
 
352
        my $bin = $self->object_get_attribute('compile','modelsim_bin');
353
        my $modelsim_bin=  $ENV{MODELSIM_BIN};
354
        $col=0;
355
        $self->object_add_attribute('compile','modelsim_bin',$modelsim_bin) if (!defined $bin && defined $modelsim_bin);
356
        $table->attach(gen_label_help("Path to modelsim/bin directory. You can set a default path as MODELSIM_BIN envirement variable in ~/.bashrc file.
357
e.g.  export MODELSIM_BIN=/home/alireza/altera/modeltech/bin",'Modelsim  bin:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
358
        $table->attach(get_dir_in_object ($self,'compile','modelsim_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
359
 
360
        return $table;
361
 
362
}
363
 
364
 
365
sub remove_pin_assignment{
366
        my $self=shift;
367
        $self->object_remove_attribute('compile_pin_pos');
368
        $self->object_remove_attribute('compile_pin');
369
        $self->object_remove_attribute('compile_assign_type');
370
        $self->object_remove_attribute('compile_pin_range_hsb');
371
        $self->object_remove_attribute('compile_pin_range_lsb');
372
}
373
 
374
 
375 38 alirezamon
 
376
 
377
 
378
sub add_new_fpga_board{
379
        my ($self,$name,$top,$target_dir,$end_func)=@_;
380
        my $window = def_popwin_size(50,80,"Add New FPGA Board",'percent');
381
        my $table = def_table(2, 2, FALSE);
382
        my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef);
383
        $scrolled_win->set_policy( "automatic", "automatic" );
384
        $scrolled_win->add_with_viewport($table);
385
 
386
 
387
        my $mtable = def_table(10, 10, FALSE);
388
 
389
        my $next=def_image_button('icons/plus.png','Add');
390
        my $back=def_image_button('icons/left.png','Previous');
391
    my $auto=def_image_button('icons/advance.png','Auto-fill');
392
 
393
        $mtable->attach_defaults($scrolled_win,0,10,0,9);
394
        $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
395
        $mtable->attach($auto,5,6,9,10,'shrink','shrink',2,2);
396
        $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
397
 
398
        set_tip($auto, "Auto-fill JTAG configuration. The board must be powered on and be connecred to the PC.");
399
 
400
 
401
 
402
        my $widgets= add_new_fpga_board_widgets($self,$name,$top,$target_dir,$end_func);
403
        my ($Twin,$tview)=create_text();
404
        add_colors_to_textview($tview);
405
 
406
        my $v1=gen_vpaned($widgets,0.3,$Twin);
407
 
408
        $table->attach_defaults($v1,0,3,0,2);
409
        #$table->attach_defaults( $Twin,0,3,1,2);       
410
 
411
 
412
 
413
 
414
        $back-> signal_connect("clicked" => sub{
415
 
416
                $window->destroy;
417
                select_compiler($self,$name,$top,$target_dir,$end_func);
418
 
419
        });
420
 
421
        $next-> signal_connect("clicked" => sub{
422
                my $result = add_new_fpga_board_files($self);
423
                if(! defined $result ){
424
                        select_compiler($self,$name,$top,$target_dir,$end_func);
425
                        message_dialog("The new board has been added successfully!");
426
 
427
                        $window->destroy;
428
 
429
                }else {
430
                        show_info(\$tview," ");
431
                        show_colored_info(\$tview,$result,'red');
432
 
433
                }
434
 
435
 
436
 
437
        });
438
 
439
        $auto-> signal_connect("clicked" => sub{
440
                my $pid;
441
                my $hw;
442
                my $dir = Cwd::getcwd();
443
                my $project_dir   = abs_path("$dir/../../"); #mpsoc directory address           
444
                my $command=  "$project_dir/mpsoc/src_c/jtag/jtag_libusb/list_usb_dev";
445
                add_info(\$tview,"$command\n");
446
                my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
447
                if(length $stderr>1){
448
                        add_colored_info(\$tview,"$stderr\n",'red');
449
                        add_colored_info(\$tview,"$command was not run successfully!\n",'red');
450
                }else {
451
 
452
                        if($exit){
453
                                add_colored_info(\$tview,"$stdout\n",'red');
454
                                add_colored_info(\$tview,"$command was not run successfully!\n",'red');
455
                        }else{
456
                                add_info(\$tview,"$stdout\n");
457
                                my @a=split /vid=9fb/, $stdout;
458
                                if(defined $a[1]){
459
                                        my @b=split /pid=/, $a[1];
460
                                        my @c=split /\n/, $b[1];
461
                                        $pid=$c[0];
462
                                        $self->object_add_attribute('compile','quartus_pid',$pid);
463
                                        add_colored_info(\$tview,"Detected PID: $pid\n",'blue');
464
 
465
                                }else{
466
                                        add_colored_info(\$tview,"The Altera vendor ID of 9fb is not detected. Make sure You have connected your Altera board to your USB port\n",'red');
467
                                        return;
468
                                }
469
                        }
470
                }
471
 
472
 
473
                $command=  "$ENV{QUARTUS_BIN}/jtagconfig";
474
                add_info(\$tview,"$command\n");
475
                ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
476
                if(length $stderr>1){
477
                        add_colored_info(\$tview,"$stderr\n",'red');
478
                        add_colored_info(\$tview,"$command was not run successfully!\n",'red');
479
                }else {
480
 
481
                        if($exit){
482
                                add_colored_info(\$tview,"$stdout\n",'red');
483
                                add_colored_info(\$tview,"$command was not run successfully!\n",'red');
484
                        }else{
485
                                add_info(\$tview,"$stdout\n");
486
                                my @a=split /1\)\s+/, $stdout;
487
                                if(defined $a[1]){
488
                                        my @b=split /\s+/, $a[1];
489
                                        $hw=$b[0];
490
                                        $self->object_add_attribute('compile','quartus_hardware',$hw);
491
                                        add_colored_info(\$tview,"Detected Hardware: $hw\n",'blue');
492
                                        my $qsf=$self->object_get_attribute('compile','quartus_qsf');
493
                                        if(!defined $qsf ){
494
                                                add_colored_info (\$tview,"Cannot detect devce location in JTAG chin. Please enter the QSF file or fill in manually \n",'red');
495
 
496
                                        }else{
497
                                                #search for device nam ein qsf file
498
                                                $qsf=add_project_dir_to_addr($qsf);
499
                                                if (!(-f $qsf)){
500
                                                        add_colored_info (\$tview, "Error Could not find $qsf file!\n");
501
                                                        return;
502
                                                }
503
                                                my $str=load_file($qsf);
504
                                                my $dw= capture_string_between(' DEVICE ',$str,"\n");
505
                                                if(defined $dw){
506
                                                add_colored_info(\$tview,"Device name in qsf file is: $dw\n",'blue');
507
                                                @b=split /\n/, $a[1];
508
 
509
                                                #capture device name in JTAG chain
510
                                                        my @f=(0);
511
                                                        foreach my $c (@b){
512
                                                                my @e=split /\s+/, $c;
513
                                                                push(@f,$e[2]) if(defined $e[2]);
514
                                                        }
515
 
516
                                                        my $pos=find_the_most_similar_position($dw ,@f);
517
                                                        $self->object_add_attribute('compile','quartus_device',$pos);
518
                                                add_colored_info(\$tview,"$dw has the most similarity with $f[$pos] in JTAG chain\n",'blue');
519
 
520
 
521
                                            }else{
522
                                                add_colored_info (\$tview, "Could not find device name in the $qsf file!\n");
523
                                            }
524
 
525
                                        }
526
 
527
 
528
                                }else{
529
                                        #add_colored_info(\$tview,"The Altera vendor ID of 9fb is not detected. Make sure You have connected your Altera board to your USB port\n",'red');
530
 
531
                                }
532
 
533
                        }
534
                }
535
                $widgets->destroy();
536
                $widgets= add_new_fpga_board_widgets($self,$name,$top,$target_dir,$end_func);
537
                $v1-> pack1($widgets, TRUE, TRUE);
538
                #$table->attach_defaults($widgets,0,3,0,1); 
539
                $table->show_all();
540
         #      my $cmd=" $ENV{'QUARTUS_BIN'}"
541
 
542
        });
543
 
544
 
545
 
546
        $window->add ($mtable);
547
        $window->show_all();
548
 
549
}
550
 
551
 
552
 
553
 
554
 
555
 
556
 
557
 
558
 
559
 
560
sub add_new_fpga_board_widgets{
561
        my ($self,$name,$top,$target_dir,$end_func)=@_;
562
        my $table = def_table(2, 2, FALSE);
563
 
564
        my $help1="FPGA Board name. Do not use any space in given name";
565
        my $help2="Path to FPGA board qsf file. In your Altra board installation CD or in the Internet search for a QSF file containing your FPGA device name with other necessary global project setting including the pin assignments (e.g DE10_Nano_golden_top.qsf).";
566
        my $help3="Path to FPGA_board_top.v file. In your Altra board installation CD or in the Internet search for a verilog file containing all your FPGA device IO ports (e.g DE10_Nano_golden_top.v).";
567
        my $help4="FPGA Borad USB-Blaster product ID (PID). Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find PID. Optinally you can run mpsoc/
568
src_c/jtag/jtag_libusb/list_usb_dev to find your USB-Blaster PID. Search for PID of a device having 9fb (altera) Vendor ID (VID)";
569
        my $help5="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your hardware name. Optinally you can run \$QUARTUS_BIN/jtagconfig to find your programming hardware name.
570
an example of output from the 'jtagconfig' command:
571
\t  1) ByteBlasterMV on LPT1
572
\t       090010DD   EPXA10
573
\t       049220DD   EPXA_ARM922
574
or
575
\t   1) DE-SoC [1-3]
576
\t       48A00477   SOCVHP5
577
\t       02D020DC   5CS(EBA6ES|XFC6c6ES)
578
ByteBlasterMV \& DE-SoC are the programming hardware name.";
579
my $help6="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your devive location in jtag chain. Optinally you can run \$QUARTUS_BIN/jtagconfig to find your target device location in jtag chain.";
580
 
581
 
582
 
583
 
584
        my @info = (
585
        { label=>"FPGA Borad name:",                   param_name=>'quartus_board', type=>"Entry",     default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef},
586
        { label=>'FPGA board golden top QSF file:',    param_name=>'quartus_qsf',   type=>"FILE_path", default_val=>undef, content=>"qsf", info=>$help2, param_parent=>'compile', ref_delay=>undef},
587
        { label=>"FPGA board golden top verilog file", param_name=>'quartus_v',     type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef },
588
        );
589
 
590
        my @usb = (
591
        { label=>"FPGA Borad USB Blaster PID:",        param_name=>'quartus_pid',   type=>"Entry",     default_val=>undef, content=>undef, info=>$help4, param_parent=>'compile', ref_delay=> undef},
592
        { label=>"FPGA Borad Programming Hardware Name:", param_name=>'quartus_hardware',   type=>"Entry",     default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef},
593
        { label=>"FPGA Borad Device location in JTAG chain:", param_name=>'quartus_device',   type=>"Spin-button",     default_val=>0, content=>"0,100,1", info=>$help6, param_parent=>'compile', ref_delay=> undef},
594
        );
595
 
596
 
597
        my $col=0;
598
        my $row=0;
599
        foreach my $d (@info) {
600
                ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical");
601
        }
602
 
603
        my $labl=def_pack_vbox(FALSE, 0,(Gtk2::HSeparator->new,gen_label_in_center("FPGA Board JTAG Configuration"),Gtk2::HSeparator->new));
604
 
605
        $table->attach( $labl,0,3,$row,$row+1,'fill','shrink',2,2); $row++; $col=0;
606
 
607
        foreach my $d (@usb) {
608
                ($row,$col)=add_param_widget ($self, $d->{label}, $d->{param_name}, $d->{default_val}, $d->{type}, $d->{content}, $d->{info}, $table,$row,$col,1, $d->{param_parent}, $d->{ref_delay},undef,"vertical");
609
        }
610
 
611
 
612
        return ($row, $col, $table);
613
}
614
 
615
 
616
 
617
 
618
 
619
sub add_new_fpga_board_files{
620
        my $self=shift;
621
 
622
        #check the board name
623
        my $board_name=$self->object_get_attribute('compile','quartus_board');
624
        return "Please define the Board Name\n" if(! defined $board_name );
625
        return "Please define the Board Name\n" if(length($board_name) ==0 );
626
        my $r=check_verilog_identifier_syntax($board_name);
627
        return "Error in given Board Name: $r\n" if(defined $r );
628
 
629
        #check qsf file 
630
        my $qsf=$self->object_get_attribute('compile','quartus_qsf');
631
        return "Please define the QSF file\n" if(!defined $qsf );
632
 
633
        #check v file 
634
        my $top=$self->object_get_attribute('compile','quartus_v');
635
        return "Please define the verilog file file\n" if(!defined $top );
636
 
637
        #check PID
638
        my $pid=$self->object_get_attribute('compile','quartus_pid');
639
        return "Please define the PID\n" if(! defined $pid );
640
        return "Please define the PID\n" if(length($pid) ==0 );
641
 
642
        #check Hardware name
643
        my $hw=$self->object_get_attribute('compile','quartus_hardware');
644
        return "Please define the Hardware Name\n" if(! defined $hw );
645
        return "Please define the Hardware Name\n" if(length($hw) ==0 );
646
 
647
 
648
        #check Device name name
649
        my $dw=$self->object_get_attribute('compile','quartus_device');
650
        return "Please define targeted Device location in JTAG chain. The device location must be larger than zero.\n" if( $dw == 0 );
651
 
652
 
653
 
654
        #make board directory
655
        my $dir = Cwd::getcwd();
656
        my $path="$dir/../boards/$board_name";
657
        mkpath($path,1,01777);
658
        return "Error cannot make $path path" if ((-d $path)==0);
659
 
660
        #generate new qsf file
661
        $qsf=add_project_dir_to_addr($qsf);
662
        $top=add_project_dir_to_addr($top);
663
        open my $file, "<", $qsf or return "Error Could not open $qsf file in read mode!";
664
        open my $newqsf, ">", "$path/$board_name.qsf" or return "Error Could not create $path/$board_name.qsf file in write mode!";
665
 
666
        #remove the lines contain following strings
667
        my @p=("TOP_LEVEL_ENTITY","VERILOG_FILE","SYSTEMVERILOG_FILE","VHDL_FILE","AHDL_FILE","PROJECT_OUTPUT_DIRECTORY" );
668
        while (my $line = <$file>){
669
                if ($line =~ /\Q$p[0]\E/ || $line =~ /\Q$p[1]\E/ || $line =~ /\Q$p[2]\E/ ||  $line =~ /\Q$p[3]\E/ ||  $line =~ /\Q$p[4]\E/){#dont copy the line contain TOP_LEVEL_ENTITY
670
 
671
                }
672
 
673
                else{
674
                        print $newqsf $line;
675
                }
676
 
677
        }
678
        print $newqsf "\nset_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files\n";
679
 
680
        close $newqsf;
681
        close $file;
682
        copy($top,"$path/$board_name.v");
683
 
684
        #generate jtag_intfc.sh
685
        open $file, ">", "$path/jtag_intfc.sh" or return "Error: Could not create $path/jtag_intfc.sh file in write mode!";
686
        my $jtag;
687
        if($pid eq 6001 || $pid eq 6002 || $pid eq 6003){
688
                $jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_libusb -a \$PRODUCT_ID\"";
689
 
690
        }else{
691
                $jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_quartus_stp -a \$HARDWARE_NAME -b \$DEVICE_NAME\"";
692
 
693
        }
694
        print $file "#!/bin/sh
695
 
696
PRODUCT_ID=\"0x$pid\"
697
HARDWARE_NAME=\'$hw *\'
698
DEVICE_NAME=\"\@$dw*\"
699
 
700
$jtag
701
 
702
        ";
703
        close $file;
704
 
705
 
706
        #generate program_device.sh
707
        open $file, ">", "$path/program_device.sh" or return "Error: Could not create $path/program_device.sh file in write mode!";
708
 
709
 
710
print $file "#!/bin/sh
711
 
712
#usage:
713
#       sh program_device.sh  programming_file.sof
714
 
715
#programming file
716
#given as an argument:  \$1
717
 
718
#Programming mode
719
PROG_MODE=jtag
720
 
721
#cable name. Connect the board to ur PC and then run jtagconfig in terminal to find the cable name
722
NAME=\"$hw\"
723
 
724
#device name
725
DEVICE=\@$dw".'
726
 
727
 
728
#programming command
729
if [ -n "${QUARTUS_BIN+set}" ]; then
730
  $QUARTUS_BIN/quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}"
731
else
732
  quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}"
733
fi
734
';
735
 
736
close $file;
737
$self->object_add_attribute('compile','board',$board_name);
738
 
739
        return undef;
740
}
741
 
742 34 alirezamon
sub  get_pin_assignment{
743 38 alirezamon
        my ($self,$name,$top,$target_dir,$end_func)=@_;
744 34 alirezamon
        my $window = def_popwin_size(80,80,"Step 2: Pin Assignment",'percent');
745
 
746
        my $table = def_table(2, 2, FALSE);
747
        my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef);
748
        $scrolled_win->set_policy( "automatic", "automatic" );
749
        $scrolled_win->add_with_viewport($table);
750
 
751
 
752
        my $mtable = def_table(10, 10, FALSE);
753
 
754
        my $next=def_image_button('icons/right.png','Next');
755
        my $back=def_image_button('icons/left.png','Previous');
756
 
757
 
758
        $mtable->attach_defaults($scrolled_win,0,10,0,9);
759
        $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
760
        $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
761
 
762 38 alirezamon
 
763 34 alirezamon
 
764 38 alirezamon
 
765 34 alirezamon
 
766 38 alirezamon
        my $board_name=$self->object_get_attribute('compile','board');
767
        #copy board jtag_intfc.sh file 
768
        my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
769
        copy("../boards/$board_name/jtag_intfc.sh","${fpath}../sw/jtag_intfc.sh");
770 34 alirezamon
 
771 38 alirezamon
        #copy board program_device.sh file 
772
        copy("../boards/$board_name/program_device.sh","${fpath}../program_device.sh");
773 34 alirezamon
 
774
        #get boards pin list
775 38 alirezamon
        my $top_v= "../boards/$board_name/$board_name.v";
776
        if(!-f $top_v){
777
                message_dialog("Error: Could not load the board pin list. The $top_v does not exist!");
778 34 alirezamon
                $window->destroy;
779
        }
780 38 alirezamon
 
781
        my $board=read_top_v_file($top_v);
782 34 alirezamon
 
783
        # Write object file
784
        #open(FILE,  ">lib/soc/tttttttt") || die "Can not open: $!";
785
        #print FILE Data::Dumper->Dump([\%$board],['board']);
786
        #close(FILE) || die "Error closing file: $!";
787
 
788
        my @dirs = ('Input', 'Bidir', 'Output');
789
        my %models;
790
        foreach my $p (@dirs){
791
                my %pins=$board->board_get_pin($p);
792
                $models{$p}=gen_combo_model(\%pins);
793
 
794
        }
795
 
796
        my $row=0;
797
        my $col=0;
798
        my @lables= ('Port Direction','Port Range     ','Port name      ','Assigment Type','Board Port name ','Board Port Range');
799
        foreach my $p (@lables){
800
                my $l=gen_label_in_left($p);
801
                $l->set_markup("<b>  $p    </b>");
802
                $table->attach ($l, $col,$col+1, $row, $row+1,'fill','shrink',2,2);
803
                $col++
804
        }
805
        $row++;
806
 
807
 
808
        #read port list 
809
        my $vdb=read_verilog_file($top);
810
        my %port_type=get_ports_type($vdb,"${name}_top");
811
        my %port_range=get_ports_rang($vdb,"${name}_top");
812
        my %param = $vdb->get_modules_parameters("${name}_top");
813
 
814
        foreach my $p (sort keys %port_type){
815
                my $porttype=$port_type{$p};
816
                my $portrange=$port_range{$p};
817
 
818
                if  (length($portrange)!=0){
819
                        #replace parameter with their values            
820
                        my @a= split (/\b/,$portrange);
821
                        foreach my $l (@a){
822
                                my $value=$param{$l};
823
                                if(defined $value){
824
                                        chomp $value;
825
                                        ($portrange=$portrange)=~ s/\b$l\b/$value/g      if(defined $param{$l});
826
                                }
827
                        }
828
                        $portrange = "[ $portrange ]" ;
829
                }
830
 
831
                my $label1= gen_label_in_left("  $porttype");
832
                my $label2= gen_label_in_left("  $portrange");
833
                my $label3= gen_label_in_left("  $p");
834
 
835
                $table->attach($label1, 0,1, $row, $row+1,'fill','shrink',2,2);
836
                $table->attach($label2, 1,2, $row, $row+1,'fill','shrink',2,2);
837
                $table->attach($label3, 2,3, $row, $row+1,'fill','shrink',2,2);
838
 
839
                my $assign_type= "Direct,Negate(~)";
840
                if ($porttype eq  'input') {
841
                        my $assign_combo=gen_combobox_object($self,'compile_assign_type',$p,$assign_type,'Direct',undef,undef);
842
                        $table->attach( $assign_combo, 3,4, $row, $row+1,'fill','shrink',2,2);
843
                }
844
 
845
                my $type= ($porttype eq  'input') ? 'Input' :
846
                          ($porttype eq  'output')? 'Output' : 'Bidir';
847
 
848
                my $combo= gen_tree_combo($models{$type});
849
                my $saved=$self->object_get_attribute('compile_pin_pos',$p);
850
                my $box;
851
                my $loc=$row;
852
                if(defined $saved) {
853
                          my @indices=@{$saved};
854
                          my $path = Gtk2::TreePath->new_from_indices(@indices);
855
                          my $iter = $models{$type}->get_iter($path);
856
                          undef $path;
857
                          $combo->set_active_iter($iter);
858
                          $box->destroy if(defined $box);
859
                          my $text=$self->object_get_attribute('compile_pin',$p);
860
                          $box=get_range ($board,$self,$type,$text,$portrange,$p);
861
                          $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
862
                }
863
 
864
 
865
 
866
 
867
                $combo->signal_connect("changed" => sub{
868
 
869
                        #get and saved new value
870
                        my $treeiter=  $combo->get_active_iter();
871
                        my $text = $models{$type}->get_value($treeiter, 0);
872
                        $self->object_add_attribute('compile_pin',$p,$text);
873
                        #get and saved value position in model
874
                        my $treepath = $models{$type}->get_path ($treeiter);
875
                        my @indices=   $treepath->get_indices();
876
                        $self->object_add_attribute('compile_pin_pos',$p,\@indices);
877
                        #update borad port range
878
                        $box->destroy if(defined $box);
879
                        $box=get_range ($board,$self,$type,$text,$portrange,$p);
880
                        $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
881
                        $table->show_all;
882
 
883
                });
884
 
885
                $table->attach($combo, 4,5, $row, $row+1,'fill','shrink',2,2);
886
 
887
 
888
 
889
 
890
 
891
 
892
 
893
                $row++;
894
 
895
        }
896
        $next-> signal_connect("clicked" => sub{
897
 
898
                $window->destroy;
899 38 alirezamon
                quartus_compilation($self,$board,$name,$top,$target_dir,$end_func);
900 34 alirezamon
 
901
        });
902
        $back-> signal_connect("clicked" => sub{
903
 
904
                $window->destroy;
905 38 alirezamon
                select_compiler($self,$name,$top,$target_dir,$end_func);
906 34 alirezamon
 
907
        });
908
 
909
 
910
        $window->add ($mtable);
911
        $window->show_all();
912
}
913
 
914
 
915
 
916
 
917
 
918
sub quartus_compilation{
919 38 alirezamon
        my ($self,$board,$name,$top,$target_dir,$end_func)=@_;
920
 
921
        my $run=def_image_button('icons/gate.png','Compile');
922 34 alirezamon
        my $back=def_image_button('icons/left.png','Previous');
923 38 alirezamon
        my $regen=def_image_button('icons/refresh.png','Regenerate Top.v');
924
        my $prog=def_image_button('icons/write.png','Program the board');
925 34 alirezamon
 
926
 
927
        my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
928
        my $board_top_file ="${fpath}Top.v";
929
        unless (-e $board_top_file ){
930
                gen_top_v($self,$board,$name,$top) ;
931
        }
932
 
933
        my ($app,$table,$tview,$window) = software_main($fpath,'Top.v');
934
        $table->attach($back,1,2,1,2,'shrink','shrink',2,2);
935
        $table->attach($regen,4,5,1,2,'shrink','shrink',2,2);
936 38 alirezamon
        $table->attach ($run,7, 8, 1,2,'shrink','shrink',2,2);
937
        $table->attach($prog,9,10,1,2,'shrink','shrink',2,2);
938 34 alirezamon
 
939
 
940 38 alirezamon
 
941 34 alirezamon
        $regen-> signal_connect("clicked" => sub{
942
                my $dialog = Gtk2::MessageDialog->new (my $window,
943
                                      'destroy-with-parent',
944
                                      'question', # message type
945
                                      'yes-no', # which set of buttons?
946
                                      "Are you sure you want to regenaret the Top.v file? Note that any changes you have made will be lost");
947
                my $response = $dialog->run;
948
                if ($response eq 'yes') {
949
                        gen_top_v($self,$board,$name,$top);
950
                        $app->load_source("$board_top_file");
951
                }
952
                $dialog->destroy;
953
 
954
        });
955
 
956
 
957
 
958
        $back-> signal_connect("clicked" => sub{
959
 
960
                $window->destroy;
961
                get_pin_assignment($self,$name,$top,$target_dir);
962
 
963
        });
964
 
965
 
966
        #compile
967
        $run-> signal_connect("clicked" => sub{
968
                set_gui_status($self,'save_project',1);
969
                $app->do_save();
970
                my $error = 0;
971
                add_info(\$tview,"CREATE: start creating Quartus project in $target_dir\n");
972
 
973
                #get list of source file
974
                add_info(\$tview,"        Read the list of all source files $target_dir/src_verilog\n");
975
                my @files = File::Find::Rule->file()
976
                            ->name( '*.v','*.V','*.sv' )
977
                            ->in( "$target_dir/src_verilog" );
978
 
979
                #make sure source files have key word 'module' 
980
                my @sources;
981
                foreach my $p (@files){
982
                        push (@sources,$p)      if(check_file_has_string($p,'module'));
983
                }
984
                my $files = join ("\n",@sources);
985
                add_info(\$tview,"$files\n");
986
 
987
                #creat project qsf file
988
                my $qsf_file="$target_dir/${name}.qsf";
989
                save_file ($qsf_file,"# Generated using ProNoC\n");
990
 
991
                #append global assignets to qsf file
992
                my $board_name=$self->object_get_attribute('compile','board');
993 38 alirezamon
                my @qsfs =   glob("../boards/$board_name/*.qsf");
994 34 alirezamon
                if(!defined $qsfs[0]){
995 38 alirezamon
                        message_dialog("Error: ../boards/$board_name folder does not contain the qsf file.!");
996 34 alirezamon
                        $window->destroy;
997
                }
998
 
999
 
1000
                my $assignment_file =  $qsfs[0];
1001
 
1002
                if(-f $assignment_file){
1003
                        merg_files ($assignment_file,$qsf_file);
1004
                }
1005
 
1006
 
1007
                #add the list of source fils to qsf file
1008
                my $s="\n\n\n set_global_assignment -name TOP_LEVEL_ENTITY Top\n";
1009
                foreach my $p (@sources){
1010
                        my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
1011
                        $s="$s set_global_assignment -name VERILOG_FILE $p\n" if ($suffix eq ".v");
1012
                        $s="$s set_global_assignment -name SYSTEMVERILOG_FILE $p\n" if ($suffix eq ".sv");
1013
 
1014
                }
1015
                append_text_to_file($qsf_file,$s);
1016
                add_info(\$tview,"\n Qsf file has been created\n");
1017
 
1018
                #start compilation
1019
                my $Quartus_bin= $self->object_get_attribute('compile','quartus_bin');;
1020
                add_info(\$tview, "Start Quartus compilation.....\n");
1021
                my @compilation_command =(
1022
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status' ",
1023
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status' ",
1024
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status' ",
1025
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_sta --64bit $name;echo \$? > status' ");
1026
 
1027
                foreach my $cmd (@compilation_command){
1028
                        add_info(\$tview,"$cmd\n");
1029
                        unlink "$target_dir/status";
1030
                        my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout( $cmd);
1031
                        open(my $fh,  "<$target_dir/status") || die "Can not open: $!";
1032
                        read($fh,my $status,1);
1033
                        close($fh);
1034
                        if("$status" != "0"){
1035
                                ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/output_files/\" \n grep -h \"Error (\" *");
1036
                                add_colored_info(\$tview,"$stdout\n Quartus compilation failed !\n",'red');
1037
                                $error=1;
1038
                                last;
1039
                        }
1040
                }
1041
                add_colored_info(\$tview,"Quartus compilation is done successfully in $target_dir!\n", 'blue') if($error==0);
1042 38 alirezamon
                if (defined $end_func){
1043
                        if ($error==0){
1044
                                $end_func->($self);
1045
                                $window->destroy;
1046
                        }else {
1047
                                message_dialog("Error in Quartus compilation!",'error');
1048
                        }
1049
                }
1050 34 alirezamon
 
1051
        });
1052
 
1053
 
1054 38 alirezamon
        #Programe the board 
1055
        $prog-> signal_connect("clicked" => sub{
1056
                my $error = 0;
1057
                my $sof_file="$target_dir/output_files/${name}.sof";
1058
                my $bash_file="$target_dir/program_device.sh";
1059 34 alirezamon
 
1060 38 alirezamon
                add_info(\$tview,"Programe the board using quartus_pgm and $sof_file file\n");
1061
                #check if the programming file exists
1062
                unless (-f $sof_file) {
1063
                        add_colored_info(\$tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red');
1064
                        $error=1;
1065
                }
1066
                #check if the program_device.sh file exists
1067
                unless (-f $bash_file) {
1068
                        add_colored_info(\$tview,"\tThe $bash_file does not exists! This file veries depend on your target board and must be available inside mpsoc/boards/[board_name].\n", 'red');
1069
                        $error=1;
1070
                }
1071
                return if($error);
1072
                my $command = "sh $bash_file $sof_file";
1073
                add_info(\$tview,"$command\n");
1074
                my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
1075
                if(length $stderr>1){
1076
                        add_colored_info(\$tview,"$stderr\n",'red');
1077
                        add_colored_info(\$tview,"Board was not programed successfully!\n",'red');
1078
                }else {
1079 34 alirezamon
 
1080 38 alirezamon
                        if($exit){
1081
                                add_colored_info(\$tview,"$stdout\n",'red');
1082
                                add_colored_info(\$tview,"Board was not programed successfully!\n",'red');
1083
                        }else{
1084
                                add_info(\$tview,"$stdout\n");
1085
                                add_colored_info(\$tview,"Board is programed successfully!\n",'blue');
1086 34 alirezamon
 
1087 38 alirezamon
                        }
1088
 
1089
                }
1090
        });
1091 34 alirezamon
 
1092
 
1093
}
1094
 
1095
 
1096
 
1097
 
1098
 
1099
 
1100
sub modelsim_compilation{
1101
        my ($self,$name,$top,$target_dir)=@_;
1102
        #my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
1103
 
1104
 
1105
        my $run=def_image_button('icons/run.png','run');
1106
        my $back=def_image_button('icons/left.png','Previous');
1107
        my $regen=def_image_button('icons/refresh.png','Regenerate testbench.v');
1108
        #create testbench.v
1109
        gen_modelsim_soc_testbench ($self,$name,$top,$target_dir) if ((-f "$target_dir/src_verilog/testbench.v")==0);
1110
 
1111
 
1112
 
1113
        my ($app,$table,$tview,$window) = software_main("$target_dir/src_verilog",'testbench.v');
1114
        $table->attach($back,1,2,1,2,'shrink','shrink',2,2);
1115
        $table->attach($regen,4,5,1,2,'shrink','shrink',2,2);
1116
        $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
1117
 
1118
 
1119
 
1120
        $regen-> signal_connect("clicked" => sub{
1121
                my $dialog = Gtk2::MessageDialog->new (my $window,
1122
                                      'destroy-with-parent',
1123
                                      'question', # message type
1124
                                      'yes-no', # which set of buttons?
1125
                                      "Are you sure you want to regenaret the testbench.v file? Note that any changes you have made will be lost");
1126
                my $response = $dialog->run;
1127
                if ($response eq 'yes') {
1128
                        gen_modelsim_soc_testbench ($self,$name,$top,$target_dir);
1129
                        $app->load_source("$target_dir/src_verilog/testbench.v");
1130
                }
1131
                $dialog->destroy;
1132
 
1133
        });
1134
 
1135
 
1136
 
1137
 
1138
 
1139
 
1140
        $back-> signal_connect("clicked" => sub{
1141
 
1142
                $window->destroy;
1143
                select_compiler($self,$name,$top,$target_dir);
1144
 
1145
        });
1146
 
1147
 
1148
        #creat modelsim dir
1149
        add_info(\$tview,"creat Modelsim dir in $target_dir\n");
1150
        my $model="$target_dir/Modelsim";
1151
        rmtree("$model");
1152
        mkpath("$model/rtl_work",1,01777);
1153
 
1154
        #create modelsim.tcl file
1155
my $tcl="#!/usr/bin/tclsh
1156
 
1157
 
1158
transcript on
1159
if {[file exists rtl_work]} {
1160
        vdel -lib rtl_work -all
1161
}
1162
vlib rtl_work
1163
vmap work rtl_work
1164
";
1165
 
1166
#Get the list of  all verilog files in src_verilog folder
1167
        add_info(\$tview,"Get the list of all verilog files in src_verilog folder\n");
1168
        my @files = File::Find::Rule->file()
1169
                ->name( '*.v','*.V','*.sv' )
1170
                ->in( "$target_dir/src_verilog" );
1171
#make sure source files have key word 'module' 
1172
        my @sources;
1173
        foreach my $p (@files){
1174
                my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
1175
                if(check_file_has_string($p,'module')){
1176
                        if ($suffix eq ".sv"){$tcl=$tcl."vlog -sv -work work +incdir+$path \{$p\}\n";}
1177
                        else {$tcl=$tcl."vlog -vlog01compat -work work +incdir+$path \{$p\}\n";}
1178
                }
1179
        }
1180
 
1181
$tcl="$tcl
1182
vsim -t 1ps  -L rtl_work -L work -voptargs=\"+acc\"  testbench
1183
 
1184
add wave *
1185
view structure
1186
view signals
1187
run -all
1188
";
1189 38 alirezamon
        add_info(\$tview,"Create run.tcl file\n");
1190 34 alirezamon
        save_file ("$model/run.tcl",$tcl);
1191
        $run -> signal_connect("clicked" => sub{
1192
                set_gui_status($self,'save_project',1);
1193
                $app->do_save();
1194
                my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin');
1195
                my $cmd="cd $target_dir; $modelsim_bin/vsim -do $model/run.tcl";
1196 38 alirezamon
                add_info(\$tview,"$cmd\n");
1197 34 alirezamon
                my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
1198 38 alirezamon
                if(length $stderr>1){
1199
                        add_colored_info(\$tview,"$stderr\n","red");
1200
 
1201 34 alirezamon
                }else {
1202
                        add_info(\$tview,"$stdout\n");
1203
                }
1204
 
1205
        });
1206
 
1207
        #$window->show_all();
1208
}
1209
 
1210
 
1211 38 alirezamon
# source files : $target_dir/src_verilog
1212
# work dir : $target_dir/src_verilog
1213 34 alirezamon
 
1214
sub verilator_compilation {
1215 38 alirezamon
        my ($top_ref,$target_dir,$outtext)=@_;
1216 34 alirezamon
 
1217 38 alirezamon
        my %tops = %{$top_ref};
1218 34 alirezamon
        #creat verilator dir
1219
        add_info(\$outtext,"creat verilator dir in $target_dir\n");
1220
        my $verilator="$target_dir/verilator";
1221
        rmtree("$verilator/rtl_work");
1222
        rmtree("$verilator/processed_rtl");
1223
        mkpath("$verilator/rtl_work/",1,01777);
1224
        mkpath("$verilator/processed_rtl/",1,01777);
1225
 
1226
 
1227
        #copy all verilog files in rtl_work folder
1228
        add_info(\$outtext,"Copy all verilog files in rtl_work folder\n");
1229
        my @files = File::Find::Rule->file()
1230 38 alirezamon
                ->name( '*.v','*.V','*.sv','*.vh')
1231 34 alirezamon
                ->in( "$target_dir/src_verilog" );
1232
        foreach my $file (@files) {
1233
                copy($file,"$verilator/rtl_work/");
1234
        }
1235 38 alirezamon
 
1236
        @files = File::Find::Rule->file()
1237
                ->name( '*.sv','*.vh' )
1238
            ->in( "$target_dir/src_verilog" );
1239
        foreach my $file (@files) {
1240
                copy($file,"$verilator/processed_rtl");
1241
        }
1242
 
1243
 
1244 34 alirezamon
 
1245
        #"split all verilog modules in separate  files"
1246
        add_info(\$outtext,"split all verilog modules in separate files\n");
1247
        my $split = Verilog::EditFiles->new
1248
        (outdir => "$verilator/processed_rtl",
1249
        translate_synthesis => 0,
1250
        celldefine => 0,
1251
        );
1252
        $split->read_and_split(glob("$verilator/rtl_work/*.v"));
1253
        $split->write_files();
1254 38 alirezamon
        $split->read_and_split(glob("$verilator/rtl_work/*.sv"));
1255
        $split->write_files();
1256
 
1257 34 alirezamon
 
1258
        #run verilator
1259
        #my $cmd= "cd \"$verilator/processed_rtl\" \n xterm -e sh -c ' verilator  --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3  -CFLAGS -O3'";
1260 38 alirezamon
        foreach my $top (sort keys %tops) {
1261
                my $cmd= "cd \"$verilator/processed_rtl\" \n  verilator  --cc $tops{$top} --profile-cfuncs --prefix \"$top\" -O3  -CFLAGS -O3";
1262
                add_info(\$outtext,"$cmd\n");
1263
                my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
1264
                if(length $stderr>1){
1265
                        add_info(\$outtext,"$stderr\n");
1266
                }else {
1267
                        add_info(\$outtext,"$stdout\n");
1268
                }
1269
        }
1270
 
1271 34 alirezamon
 
1272
        #check if verilator model has been generated 
1273 38 alirezamon
        foreach my $top (sort keys %tops) {
1274
                if (-f "$verilator/processed_rtl/obj_dir/$top.cpp"){#succsess
1275
                        #generate makefile
1276
                        gen_verilator_makefile($top_ref,"$verilator/processed_rtl/obj_dir/Makefile");
1277
 
1278
                }else {
1279
                        return 0;
1280
                }
1281
        }
1282
        return 1;
1283
}
1284
 
1285
 
1286
sub gen_verilator_makefile{
1287
        my ($top_ref,$target_dir) =@_;
1288
        my %tops = %{$top_ref};
1289
        my $p='';
1290
        my $q='';
1291
        my $h='';
1292
        my $l;
1293
        foreach my $top (sort keys %tops) {
1294
                $p = "$p ${top}__ALL.a ";
1295
                $q = "$q\t\$(MAKE) -f ${top}.mk\n";
1296
                $h = "$h ${top}.h ";
1297
                $l = $top;
1298
        }
1299
 
1300
 
1301
        my $make= "
1302
 
1303
default: sim
1304
 
1305
 
1306
 
1307
include $l.mk
1308
 
1309
lib:
1310
$q
1311
 
1312
 
1313
#######################################################################
1314
# Compile flags
1315
 
1316
CPPFLAGS += -DVL_DEBUG=1
1317
ifeq (\$(CFG_WITH_CCWARN),yes)  # Local... Else don't burden users
1318
CPPFLAGS += -DVL_THREADED=1
1319
CPPFLAGS += -W -Werror -Wall
1320
endif
1321
 
1322
#######################################################################
1323
# Linking final exe -- presumes have a sim_main.cpp
1324
 
1325
 
1326
sim:    testbench.o \$(VK_GLOBAL_OBJS) $p
1327
        \$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 2>&1 | c++filt
1328
 
1329
testbench.o: testbench.cpp $h
1330
 
1331
clean:
1332
        rm *.o *.a main
1333
";
1334
 
1335
 
1336
 
1337
save_file ($target_dir,$make);
1338
 
1339
 
1340
 
1341
 
1342
}
1343
 
1344
 
1345
 
1346
sub verilator_compilation_win {
1347
        my ($self,$name,$top,$target_dir)=@_;
1348
        my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
1349
        my $mtable = def_table(10, 10, FALSE);
1350
        my ($outbox,$outtext)= create_text();
1351
        add_colors_to_textview($outtext);
1352
        my $next=def_image_button('icons/run.png','Next');
1353
        my $back=def_image_button('icons/left.png','Previous');
1354
 
1355
 
1356
        $mtable->attach_defaults ($outbox ,0, 10, 4,9);
1357
        $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
1358
        $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
1359
 
1360
 
1361
 
1362
        $back-> signal_connect("clicked" => sub{
1363
 
1364
                $window->destroy;
1365
                select_compiler($self,$name,$top,$target_dir);
1366
 
1367
        });
1368
        $next-> signal_connect("clicked" => sub{
1369
 
1370
                $window->destroy;
1371
                verilator_testbench($self,$name,$top,$target_dir);
1372
 
1373
        });
1374
        my %tops;
1375
        $tops{"Vtop"}= "$name.v";
1376
        my $result = verilator_compilation (\%tops,$target_dir,$outtext);
1377
        #check if verilator model has been generated 
1378
        if ($result){
1379 34 alirezamon
                add_colored_info(\$outtext,"Veriator model has been generated successfully!",'blue');
1380
        }else {
1381
                add_colored_info(\$outtext,"Verilator compilation failed!\n","red");
1382
                $next->destroy();
1383
        }
1384
 
1385
 
1386
 
1387
 
1388
        $window->add ($mtable);
1389
        $window->show_all();
1390
 
1391
 
1392
 
1393
}
1394
 
1395 38 alirezamon
 
1396
 
1397 34 alirezamon
sub gen_verilator_soc_testbench {
1398
        my ($self,$name,$top,$target_dir)=@_;
1399
        my $verilator="$target_dir/verilator";
1400
        my $dir="$verilator/";
1401
        my $soc_top= $self->soc_get_top ();
1402
        my @intfcs=$soc_top->top_get_intfc_list();
1403
        my %PP;
1404
        my $top_port_info="IO type\t  port_size\t  port_name\n";
1405
        foreach my $intfc (@intfcs){
1406
                my $key= ( $intfc eq 'plug:clk[0]')? 'clk' :
1407
                         ( $intfc eq 'plug:reset[0]')? 'reset':
1408
                         ( $intfc eq 'plug:enable[0]')? 'en' : 'other';
1409
                my $key1="${key}1";
1410
                my $key0="${key}0";
1411
 
1412
                my @ports=$soc_top->top_get_intfc_ports_list($intfc);
1413
                foreach my $p (@ports){
1414
                        my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
1415
                        $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} top->$p=1;\n" : "top->$p=1;\n";
1416
                        $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} top->$p=0;\n" : "top->$p=0;\n";
1417
                        $top_port_info="$top_port_info $type  $range  top->$p \n";
1418
                }
1419
 
1420
 
1421
        }
1422
        my $main_c=get_license_header("testbench.cpp");
1423
$main_c="$main_c
1424
#include <stdlib.h>
1425
#include <stdio.h>
1426
#include <unistd.h>
1427
#include <string.h>
1428
#include <verilated.h>          // Defines common routines
1429
#include \"Vtop.h\"               // From Verilating \"$name.v\" file
1430
 
1431
Vtop                    *top;
1432
/*
1433
$top_port_info
1434
*/
1435
 
1436
int reset,clk;
1437
unsigned int main_time = 0; // Current simulation time
1438
 
1439
int main(int argc, char** argv) {
1440
        Verilated::commandArgs(argc, argv);   // Remember args
1441
        top     = new Vtop;
1442
 
1443
        /********************
1444
        *       initialize input
1445
        *********************/
1446
 
1447
        $PP{reset1}
1448
        $PP{en1}
1449
        main_time=0;
1450
        printf(\"Start Simulation\\n\");
1451
        while (!Verilated::gotFinish()) {
1452
 
1453
                if (main_time >= 10 ) {
1454
                        $PP{reset0}
1455
                }
1456
 
1457
 
1458
                if ((main_time & 1) == 0) {
1459
                        $PP{clk1}      // Toggle clock
1460
                        // you can change the inputs and read the outputs here in case they are captured at posedge of clock
1461
 
1462
 
1463
 
1464
                }//if
1465
                else
1466
                {
1467
                        $PP{clk0}
1468
 
1469
 
1470
 
1471
                }//else
1472
 
1473
 
1474
                main_time ++;
1475
                top->eval();
1476
                }
1477
        top->final();
1478
}
1479
 
1480
double sc_time_stamp () {       // Called by \$time in Verilog
1481
        return main_time;
1482
}
1483
";
1484
        save_file("$dir/testbench.cpp",$main_c);
1485
 
1486
 
1487
 
1488
}
1489
 
1490
 
1491
sub gen_modelsim_soc_testbench {
1492
        my ($self,$name,$top,$target_dir)=@_;
1493
        my $dir="$target_dir/src_verilog";
1494
        my $soc_top= $self->object_get_attribute('top_ip',undef);
1495
        my @intfcs=$soc_top->top_get_intfc_list();
1496
        my %PP;
1497
        my $top_port_def="// ${name}.v IO definition \n";
1498
        my $pin_assign;
1499
        my $rst_inputs='';
1500
 
1501
        #read port list 
1502
        my $vdb=read_verilog_file($top);
1503
        my %param = $vdb->get_modules_parameters("${name}_top");
1504
 
1505
 
1506
 
1507
 
1508
 
1509
 
1510
        foreach my $intfc (@intfcs){
1511
                my $key= ( $intfc eq 'plug:clk[0]')? 'clk' :
1512
                         ( $intfc eq 'plug:reset[0]')? 'reset':
1513
                         ( $intfc eq 'plug:enable[0]')? 'en' : 'other';
1514
                my $key1="${key}1";
1515
                my $key0="${key}0";
1516
 
1517
                my @ports=$soc_top->top_get_intfc_ports_list($intfc);
1518
                my $f=1;
1519
                foreach my $p (@ports){
1520
                        my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
1521
 
1522
                        $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} $p=1;\n" : "$p=1;\n";
1523
                        $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} $p=0;\n" : "$p=0;\n";
1524
 
1525
 
1526
                        if  (length($range)!=0){
1527
                                #replace parameter with their values            
1528
                                my @a= split (/\b/,$range);
1529
                                foreach my $l (@a){
1530
                                        my $value=$param{$l};
1531
                                        if(defined $value){
1532
                                                chomp $value;
1533
                                                ($range=$range)=~ s/\b$l\b/$value/g      if(defined $param{$l});
1534
                                        }
1535
                                }
1536
                                $range = "[ $range ]" ;
1537
                        }
1538
 
1539
 
1540
 
1541
                        if($type eq 'input'){
1542
                                $top_port_def="$top_port_def  reg  $range  $p;\n"
1543
                        }else{
1544
                                $top_port_def="$top_port_def  wire  $range  $p;\n"
1545
                        }
1546
                        $pin_assign=(defined $pin_assign)? "$pin_assign,\n\t\t.$p($p)":  "\t\t.$p($p)";
1547
                        $rst_inputs= "$rst_inputs $p=0;\n" if ($key eq 'other' && $type eq 'input' );
1548
                }
1549
 
1550
 
1551
        }
1552
 
1553
my $test_v= get_license_header("testbench.v");
1554
 
1555
$test_v ="$test_v
1556
 
1557
`timescale       1ns/1ps
1558
 
1559
module testbench;
1560
 
1561
$top_port_def
1562
 
1563
 
1564
        $name uut (
1565
$pin_assign
1566
        );
1567
 
1568
//clock defination
1569
initial begin
1570
        forever begin
1571
        #5 $PP{clk0}
1572
        #5 $PP{clk1}
1573
        end
1574
end
1575
 
1576
 
1577
 
1578
initial begin
1579
        // reset $name module at the start up
1580
        $PP{reset1}
1581
        $PP{en1}
1582
        $rst_inputs
1583
        // deasert the reset after 200 ns
1584
        #200
1585
        $PP{reset0}
1586
 
1587
        // write your testbench here
1588
 
1589
 
1590
 
1591
 
1592
end
1593
 
1594
endmodule
1595
";
1596
        save_file("$dir/testbench.v",$test_v);
1597
 
1598
 
1599
 
1600
}
1601
 
1602
sub verilator_testbench{
1603
        my ($self,$name,$top,$target_dir)=@_;
1604
        my $verilator="$target_dir/verilator";
1605
        my $dir="$verilator";
1606
        gen_verilator_soc_testbench (@_) if((-f "$dir/testbench.cpp")==0);
1607
        #copy makefile
1608 38 alirezamon
        #copy("../script/verilator_soc_make", "$verilator/processed_rtl/obj_dir/Makefile"); 
1609 34 alirezamon
 
1610
 
1611
        my ($app,$table,$tview,$window) = software_main($dir,'testbench.cpp');
1612
 
1613
 
1614
        my $make = def_image_button('icons/gen.png','Compile');
1615
        my $regen=def_image_button('icons/refresh.png','Regenerate Testbench.cpp');
1616
        my $run = def_image_button('icons/run.png','Run');
1617
        my $back=def_image_button('icons/left.png','Previous');
1618
 
1619
        $table->attach ($back,1,2,1,2,'shrink','shrink',0,0);
1620
        $table->attach ($regen,3,4,1,2,'shrink','shrink',0,0);
1621
        $table->attach ($make,7, 8, 1,2,'shrink','shrink',0,0);
1622
        $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
1623
 
1624
        $back-> signal_connect("clicked" => sub{
1625
 
1626
                $window->destroy;
1627 38 alirezamon
                verilator_compilation_win($self,$name,$top,$target_dir);
1628 34 alirezamon
 
1629
        });
1630
 
1631
        $regen-> signal_connect("clicked" => sub{
1632
                my $dialog = Gtk2::MessageDialog->new (my $window,
1633
                                      'destroy-with-parent',
1634
                                      'question', # message type
1635
                                      'yes-no', # which set of buttons?
1636
                                      "Are you sure you want to regenaret the testbench.cpp file? Note that any changes you have made will be lost");
1637
                my $response = $dialog->run;
1638
                if ($response eq 'yes') {
1639
                        gen_verilator_soc_testbench ($self,$name,$top,$target_dir);
1640
                        $app->load_source("$dir/testbench.cpp");
1641
                }
1642
                $dialog->destroy;
1643
 
1644
        });
1645
 
1646
 
1647
        $make -> signal_connect("clicked" => sub{
1648
                $app->do_save();
1649
                copy("$dir/testbench.cpp", "$verilator/processed_rtl/obj_dir/testbench.cpp");
1650
                run_make_file("$verilator/processed_rtl/obj_dir/",$tview);
1651
 
1652
        });
1653
 
1654
        $run -> signal_connect("clicked" => sub{
1655
                my $bin="$verilator/processed_rtl/obj_dir/testbench";
1656
                if (-f $bin){
1657
                        my $cmd= "cd \"$verilator/processed_rtl/obj_dir/\" \n xterm -e sh -c $bin";
1658
                        add_info(\$tview,"$cmd\n");
1659
                        my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
1660
                        if(length $stderr>1){
1661
                                add_colored_info(\$tview,"$stderr\n",'red');
1662
                        }else {
1663
                                add_info(\$tview,"$stdout\n");
1664
                        }
1665
 
1666
                }else{
1667
                        add_colored_info(\$tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red')
1668
                }
1669
 
1670
                });
1671
 
1672
 
1673
}
1674
 
1675
 
1676
1;

powered by: WebSVN 2.1.0

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