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 34

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
sub read_csv_file{
90
        my $file=shift;
91
        open(my $fh,  "<$file") || die "Cannot open:$file; $!";
92
 
93
        my $board = soc->board_new();
94
        #read header format
95
 
96
        my $header;
97
 
98
        while (my $line= <$fh>){
99
                chomp $line;
100
                $line=remove_all_white_spaces($line);
101
                #print "l:$line\n";
102
                if(length ( $line)!=0){
103
                        if ($line !~ /\#/) {
104
                                $header= $line;
105
                                last;
106
                        }
107
 
108
 
109
                }
110
 
111
        }
112
 
113
        my @headers = split (',',$header);
114
        my $pin_name_col = get_scolar_pos('To',@headers);
115
        if(!defined $pin_name_col){
116
                message_dialog("Error: $file file has an unsupported format!");
117
                return $board;
118
        }
119
        my $direction_col = get_scolar_pos('Direction',@headers);
120
 
121
        close $fh;
122
 
123
        #save pins
124
        open( $fh,  "<$file") || die "Cannot open:$file; $!";
125
 
126
 
127
        while (my $line= <$fh>){
128
                chomp $line;
129
                my @fileds = split (',',$line);
130
                my $to = $fileds[$pin_name_col];
131
                my $direction = (defined $direction_col )?  $fileds[$direction_col] : 'Unknown';
132
                if(defined $direction && length($to)!=0){
133
                        if ($direction eq 'Input' || $direction eq 'Output' || $direction eq 'Bidir'){
134
                                $board->board_add_pin ($fileds[1],$to);
135
                        }elsif($direction eq 'Unknown'){
136
                                $board->board_add_pin ('Input',$to);
137
                                $board->board_add_pin ('Output',$to);
138
                                $board->board_add_pin ('Bidir',$to);
139
 
140
                        }
141
                }
142
 
143
        }
144
        close $fh;
145
        return $board;
146
}
147
 
148
 
149
 
150
 
151
sub gen_top_v{
152
        my ($self,$board,$name,$top)=@_;
153
 
154
        my $top_v=get_license_header("Top.v");
155
        #read port list 
156
        my $vdb=read_verilog_file($top);
157
        my %port_type=get_ports_type($vdb,"${name}_top");
158
        my %port_range=get_ports_rang($vdb,"${name}_top");
159
 
160
 
161
        my $io='';
162
        my $io_def='';
163
        my $io_assign='';
164
        my %board_io;
165
        my $first=1;
166
        foreach my $p (sort keys %port_type){
167
                my $porttype=$port_type{$p};
168
                my $portrange=$port_range{$p};
169
                my $assign_type = $self->object_get_attribute('compile_assign_type',$p);
170
                my $assign_name = $self->object_get_attribute('compile_pin',$p);
171
                my $range_hsb   = $self->object_get_attribute('compile_pin_range_hsb',$p);
172
                my $range_lsb   = $self->object_get_attribute('compile_pin_range_lsb',$p);
173
                my $assign="\t";
174
                if (defined $assign_name){
175
                        if($assign_name eq '*VCC'){
176
                                $assign= (length($portrange)!=0)? '{32{1\'b1}}' : '1\'b1';
177
                        } elsif ($assign_name eq '*GND'){
178
                                $assign= (length($portrange)!=0)? '{32{1\'b0}}' : '1\'b0';
179
                        }elsif ($assign_name eq '*NOCONNECT'){
180
                                $assign="\t";
181
 
182
                        }else{
183
 
184
                                $board_io{$assign_name}=$porttype;
185
 
186
 
187
                                my $range = (defined $range_hsb) ? "[$range_hsb : $range_lsb]" :
188
                                            (defined $range_lsb) ?  "[ $range_lsb]" : " ";
189
                                my $l=(defined $assign_type)?
190
                                        ($assign_type eq 'Direct') ? '' : '~' : '';
191
                                $assign="$l $assign_name $range";
192
 
193
 
194
                        }
195
                }
196
                $io_assign= ($first)? "$io_assign \t  .$p($assign)":"$io_assign,\n \t  .$p($assign)";
197
                $first=0;
198
        }
199
        $first=1;
200
        foreach my $p (sort keys %board_io){
201
                        $io=($first)? "\t$p" : "$io,\n\t$p";
202
                        my $dir=$board_io{$p};
203
                        my $range;
204
                        my $type= ($dir eq  'input') ? 'Input' :
205
                                  ($dir eq  'output')? 'Output' : 'Bidir';
206
                        my @r= $board->board_get_pin_range($type,$p);
207
                        if ($r[0] eq '*undefine*'){
208
                                $range="\t\t\t";
209
                        } else {
210
                                my ($min, $max) = minmax @r;
211
                                $range="\t[$max : $min]\t";
212
                        }
213
                        $io_def = "$io_def \t $dir $range $p;\n";
214
                        $first=0;
215
 
216
        }
217
        $top_v="$top_v
218
module Top (
219
$io
220
);
221
$io_def
222
 
223
        ${name}_top uut(
224
$io_assign
225
        );
226
 
227
 
228
endmodule
229
";
230
        my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
231
        my $board_top_file= "$fpath/Top.v";
232
        save_file($board_top_file,$top_v);
233
}
234
 
235
 
236
 
237
 
238
 
239
 
240
 
241
 
242
 
243
 
244
sub select_compiler {
245
        my ($self,$name,$top,$target_dir)=@_;
246
        my $window = def_popwin_size(40,40,"Step 1: Select Compiler",'percent');
247
        #get the list of boards located in "boards/*" folder
248
        my @dirs = grep {-d} glob("./lib/boards/*");
249
        my ($fpgas,$init);
250
        foreach my $dir (@dirs) {
251
                my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
252
                $init=$name;
253
                $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
254
        }
255
        my $table = def_table(2, 2, FALSE);
256
        my $col=0;
257
        my $row=0;
258
 
259
        my $compiler=gen_combobox_object ($self,'compile','type',"QuartusII,Verilator,Modelsim","QuartusII",undef,undef);
260
        $table->attach(gen_label_in_center("Compiler tool"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
261
        $table->attach($compiler,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
262
        $row++;$col=0;
263
 
264
 
265
 
266
        my $old_board_name=$self->object_get_attribute('compile','board');
267
        my $old_compiler=$self->object_get_attribute('compile','type');
268
        my $compiler_options = ($old_compiler eq "QuartusII")? select_board  ($self,$name,$top,$target_dir):
269
                               ($old_compiler eq "Modelsim")?  select_model_path  ($self,$name,$top,$target_dir):
270
                                                                gen_label_in_center(" ");
271
        $table->attach($compiler_options,$col,$col+2,$row,$row+1,'fill','shrink',2,2); $row++;
272
 
273
        $col=1;
274
        my $i;
275
        for ($i=$row; $i<5; $i++){
276
 
277
                my $temp=gen_label_in_center(" ");
278
                $table->attach_defaults ($temp, 0, 1 , $i, $i+1);
279
        }
280
        $row=$i;
281
 
282
 
283
        $window->add ($table);
284
        $window->show_all();
285
        my $next=def_image_button('icons/right.png','Next');
286
        $table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++;
287
        $next-> signal_connect("clicked" => sub{
288
                my $compiler_type=$self->object_get_attribute('compile','type');
289
                if($compiler_type eq "QuartusII"){
290
                        my $new_board_name=$self->object_get_attribute('compile','board');
291
                        if(defined $old_board_name) {
292
                                remove_pin_assignment($self) if ($old_board_name ne $new_board_name);
293
                                my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
294
                                my $board_top_file= "$fpath/Top.v";
295
                                unlink $board_top_file if ($old_board_name ne $new_board_name);
296
 
297
 
298
                        }
299
 
300
                        get_pin_assignment($self,$name,$top,$target_dir);
301
                }elsif($compiler_type eq "Modelsim"){
302
                        modelsim_compilation($self,$name,$top,$target_dir);
303
 
304
                }else{#verilator
305
                        verilator_compilation($self,$name,$top,$target_dir);
306
 
307
                }
308
 
309
                $window->destroy;
310
 
311
        });
312
 
313
        $compiler->signal_connect("changed" => sub{
314
                $compiler_options->destroy;
315
                my $new_board_name=$self->object_get_attribute('compile','type');
316
                $compiler_options = ($new_board_name eq "QuartusII")? select_board  ($self,$name,$top,$target_dir):
317
                                    ($new_board_name eq "Modelsim")?  select_model_path  ($self,$name,$top,$target_dir):
318
                                 gen_label_in_center(" ");
319
                $table->attach($compiler_options,0,2,1,2,'fill','shrink',2,2);
320
                $table->show_all;
321
 
322
        });
323
 
324
}
325
 
326
 
327
 
328
 
329
 
330
sub select_board {
331
        my ($self,$name,$top,$target_dir)=@_;
332
 
333
        #get the list of boards located in "boards/*" folder
334
        my @dirs = grep {-d} glob("./lib/boards/*");
335
        my ($fpgas,$init);
336
        foreach my $dir (@dirs) {
337
                my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
338
                $init=$name;
339
                $fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
340
        }
341
        my $table = def_table(2, 2, FALSE);
342
        my $col=0;
343
        my $row=0;
344
 
345
 
346
        my $old_board_name=$self->object_get_attribute('compile','board');
347
        $table->attach(gen_label_help("The list of supported boards are obtained from \"perl_gui/lib/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++;
348
        $table->attach(gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
349
 
350
        my $bin = $self->object_get_attribute('compile','quartus_bin');
351
        my $Quartus_bin=  $ENV{QUARTUS_BIN};
352
        $col=0;
353
        $self->object_add_attribute('compile','quartus_bin',$ENV{QUARTUS_BIN}) if (!defined $bin && defined $Quartus_bin);
354
        $table->attach(gen_label_help("Path to quartus/bin directory. You can set a default path as QUARTUS_BIN envirement variable in ~/.bashrc file.
355
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++;
356
        $table->attach(get_dir_in_object ($self,'compile','quartus_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
357
 
358
        return $table;
359
 
360
}
361
 
362
sub select_model_path {
363
        my ($self,$name,$top,$target_dir)=@_;
364
 
365
 
366
        my $table = def_table(2, 2, FALSE);
367
        my $col=0;
368
        my $row=0;
369
 
370
 
371
 
372
 
373
        my $bin = $self->object_get_attribute('compile','modelsim_bin');
374
        my $modelsim_bin=  $ENV{MODELSIM_BIN};
375
        $col=0;
376
        $self->object_add_attribute('compile','modelsim_bin',$modelsim_bin) if (!defined $bin && defined $modelsim_bin);
377
        $table->attach(gen_label_help("Path to modelsim/bin directory. You can set a default path as MODELSIM_BIN envirement variable in ~/.bashrc file.
378
e.g.  export MODELSIM_BIN=/home/alireza/altera/modeltech/bin",'Modelsim  bin:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
379
        $table->attach(get_dir_in_object ($self,'compile','modelsim_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
380
 
381
        return $table;
382
 
383
}
384
 
385
 
386
sub remove_pin_assignment{
387
        my $self=shift;
388
        $self->object_remove_attribute('compile_pin_pos');
389
        $self->object_remove_attribute('compile_pin');
390
        $self->object_remove_attribute('compile_assign_type');
391
        $self->object_remove_attribute('compile_pin_range_hsb');
392
        $self->object_remove_attribute('compile_pin_range_lsb');
393
}
394
 
395
 
396
sub  get_pin_assignment{
397
        my ($self,$name,$top,$target_dir)=@_;
398
        my $window = def_popwin_size(80,80,"Step 2: Pin Assignment",'percent');
399
 
400
        my $table = def_table(2, 2, FALSE);
401
        my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef);
402
        $scrolled_win->set_policy( "automatic", "automatic" );
403
        $scrolled_win->add_with_viewport($table);
404
 
405
 
406
        my $mtable = def_table(10, 10, FALSE);
407
 
408
        my $next=def_image_button('icons/right.png','Next');
409
        my $back=def_image_button('icons/left.png','Previous');
410
 
411
 
412
        $mtable->attach_defaults($scrolled_win,0,10,0,9);
413
        $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
414
        $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
415
 
416
 
417
 
418
 
419
 
420
        #get boards pin list
421
        my $board_name=$self->object_get_attribute('compile','board');
422
        my @csv_file =   glob("./lib/boards/$board_name/*.csv");
423
        if(!defined $csv_file[0]){
424
                message_dialog("Error: ./lib/boards/$board_name folder does not contain the csv file.!");
425
                $window->destroy;
426
        }
427
        my $board=read_csv_file($csv_file[0]);
428
 
429
        # Write object file
430
        #open(FILE,  ">lib/soc/tttttttt") || die "Can not open: $!";
431
        #print FILE Data::Dumper->Dump([\%$board],['board']);
432
        #close(FILE) || die "Error closing file: $!";
433
 
434
        my @dirs = ('Input', 'Bidir', 'Output');
435
        my %models;
436
        foreach my $p (@dirs){
437
                my %pins=$board->board_get_pin($p);
438
                $models{$p}=gen_combo_model(\%pins);
439
 
440
        }
441
 
442
        my $row=0;
443
        my $col=0;
444
        my @lables= ('Port Direction','Port Range     ','Port name      ','Assigment Type','Board Port name ','Board Port Range');
445
        foreach my $p (@lables){
446
                my $l=gen_label_in_left($p);
447
                $l->set_markup("<b>  $p    </b>");
448
                $table->attach ($l, $col,$col+1, $row, $row+1,'fill','shrink',2,2);
449
                $col++
450
        }
451
        $row++;
452
 
453
 
454
        #read port list 
455
        my $vdb=read_verilog_file($top);
456
        my %port_type=get_ports_type($vdb,"${name}_top");
457
        my %port_range=get_ports_rang($vdb,"${name}_top");
458
        my %param = $vdb->get_modules_parameters("${name}_top");
459
 
460
        foreach my $p (sort keys %port_type){
461
                my $porttype=$port_type{$p};
462
                my $portrange=$port_range{$p};
463
 
464
                if  (length($portrange)!=0){
465
                        #replace parameter with their values            
466
                        my @a= split (/\b/,$portrange);
467
                        foreach my $l (@a){
468
                                my $value=$param{$l};
469
                                if(defined $value){
470
                                        chomp $value;
471
                                        ($portrange=$portrange)=~ s/\b$l\b/$value/g      if(defined $param{$l});
472
                                }
473
                        }
474
                        $portrange = "[ $portrange ]" ;
475
                }
476
 
477
                my $label1= gen_label_in_left("  $porttype");
478
                my $label2= gen_label_in_left("  $portrange");
479
                my $label3= gen_label_in_left("  $p");
480
 
481
                $table->attach($label1, 0,1, $row, $row+1,'fill','shrink',2,2);
482
                $table->attach($label2, 1,2, $row, $row+1,'fill','shrink',2,2);
483
                $table->attach($label3, 2,3, $row, $row+1,'fill','shrink',2,2);
484
 
485
                my $assign_type= "Direct,Negate(~)";
486
                if ($porttype eq  'input') {
487
                        my $assign_combo=gen_combobox_object($self,'compile_assign_type',$p,$assign_type,'Direct',undef,undef);
488
                        $table->attach( $assign_combo, 3,4, $row, $row+1,'fill','shrink',2,2);
489
                }
490
 
491
                my $type= ($porttype eq  'input') ? 'Input' :
492
                          ($porttype eq  'output')? 'Output' : 'Bidir';
493
 
494
                my $combo= gen_tree_combo($models{$type});
495
                my $saved=$self->object_get_attribute('compile_pin_pos',$p);
496
                my $box;
497
                my $loc=$row;
498
                if(defined $saved) {
499
                          my @indices=@{$saved};
500
                          my $path = Gtk2::TreePath->new_from_indices(@indices);
501
                          my $iter = $models{$type}->get_iter($path);
502
                          undef $path;
503
                          $combo->set_active_iter($iter);
504
                          $box->destroy if(defined $box);
505
                          my $text=$self->object_get_attribute('compile_pin',$p);
506
                          $box=get_range ($board,$self,$type,$text,$portrange,$p);
507
                          $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
508
                }
509
 
510
 
511
 
512
 
513
                $combo->signal_connect("changed" => sub{
514
 
515
                        #get and saved new value
516
                        my $treeiter=  $combo->get_active_iter();
517
                        my $text = $models{$type}->get_value($treeiter, 0);
518
                        $self->object_add_attribute('compile_pin',$p,$text);
519
                        #get and saved value position in model
520
                        my $treepath = $models{$type}->get_path ($treeiter);
521
                        my @indices=   $treepath->get_indices();
522
                        $self->object_add_attribute('compile_pin_pos',$p,\@indices);
523
                        #update borad port range
524
                        $box->destroy if(defined $box);
525
                        $box=get_range ($board,$self,$type,$text,$portrange,$p);
526
                        $table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
527
                        $table->show_all;
528
 
529
                });
530
 
531
                $table->attach($combo, 4,5, $row, $row+1,'fill','shrink',2,2);
532
 
533
 
534
 
535
 
536
 
537
 
538
 
539
                $row++;
540
 
541
        }
542
        $next-> signal_connect("clicked" => sub{
543
 
544
                $window->destroy;
545
                quartus_compilation($self,$board,$name,$top,$target_dir);
546
 
547
        });
548
        $back-> signal_connect("clicked" => sub{
549
 
550
                $window->destroy;
551
                select_compiler($self,$name,$top,$target_dir);
552
 
553
        });
554
 
555
 
556
        $window->add ($mtable);
557
        $window->show_all();
558
}
559
 
560
 
561
 
562
 
563
 
564
sub quartus_compilation{
565
        my ($self,$board,$name,$top,$target_dir)=@_;
566
        my $run=def_image_button('icons/run.png','run');
567
        my $back=def_image_button('icons/left.png','Previous');
568
        my $regen=def_image_button('icons/refresh.png','Regenerate Top.v');
569
 
570
 
571
        my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
572
        my $board_top_file ="${fpath}Top.v";
573
        unless (-e $board_top_file ){
574
                gen_top_v($self,$board,$name,$top) ;
575
        }
576
 
577
        my ($app,$table,$tview,$window) = software_main($fpath,'Top.v');
578
        $table->attach($back,1,2,1,2,'shrink','shrink',2,2);
579
        $table->attach($regen,4,5,1,2,'shrink','shrink',2,2);
580
        $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
581
 
582
 
583
        $regen-> signal_connect("clicked" => sub{
584
                my $dialog = Gtk2::MessageDialog->new (my $window,
585
                                      'destroy-with-parent',
586
                                      'question', # message type
587
                                      'yes-no', # which set of buttons?
588
                                      "Are you sure you want to regenaret the Top.v file? Note that any changes you have made will be lost");
589
                my $response = $dialog->run;
590
                if ($response eq 'yes') {
591
                        gen_top_v($self,$board,$name,$top);
592
                        $app->load_source("$board_top_file");
593
                }
594
                $dialog->destroy;
595
 
596
        });
597
 
598
 
599
 
600
        $back-> signal_connect("clicked" => sub{
601
 
602
                $window->destroy;
603
                get_pin_assignment($self,$name,$top,$target_dir);
604
 
605
        });
606
 
607
 
608
        #compile
609
        $run-> signal_connect("clicked" => sub{
610
                set_gui_status($self,'save_project',1);
611
                $app->do_save();
612
                my $error = 0;
613
                add_info(\$tview,"CREATE: start creating Quartus project in $target_dir\n");
614
 
615
                #get list of source file
616
                add_info(\$tview,"        Read the list of all source files $target_dir/src_verilog\n");
617
                my @files = File::Find::Rule->file()
618
                            ->name( '*.v','*.V','*.sv' )
619
                            ->in( "$target_dir/src_verilog" );
620
 
621
                #make sure source files have key word 'module' 
622
                my @sources;
623
                foreach my $p (@files){
624
                        push (@sources,$p)      if(check_file_has_string($p,'module'));
625
                }
626
                my $files = join ("\n",@sources);
627
                add_info(\$tview,"$files\n");
628
 
629
                #creat project qsf file
630
                my $qsf_file="$target_dir/${name}.qsf";
631
                save_file ($qsf_file,"# Generated using ProNoC\n");
632
 
633
                #append global assignets to qsf file
634
                my $board_name=$self->object_get_attribute('compile','board');
635
                my @qsfs =   glob("./lib/boards/$board_name/*.qsf");
636
                if(!defined $qsfs[0]){
637
                        message_dialog("Error: ./lib/boards/$board_name folder does not contain the qsf file.!");
638
                        $window->destroy;
639
                }
640
 
641
 
642
                my $assignment_file =  $qsfs[0];
643
 
644
                if(-f $assignment_file){
645
                        merg_files ($assignment_file,$qsf_file);
646
                }
647
 
648
 
649
                #add the list of source fils to qsf file
650
                my $s="\n\n\n set_global_assignment -name TOP_LEVEL_ENTITY Top\n";
651
                foreach my $p (@sources){
652
                        my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
653
                        $s="$s set_global_assignment -name VERILOG_FILE $p\n" if ($suffix eq ".v");
654
                        $s="$s set_global_assignment -name SYSTEMVERILOG_FILE $p\n" if ($suffix eq ".sv");
655
 
656
                }
657
                append_text_to_file($qsf_file,$s);
658
                add_info(\$tview,"\n Qsf file has been created\n");
659
 
660
                #start compilation
661
                my $Quartus_bin= $self->object_get_attribute('compile','quartus_bin');;
662
                add_info(\$tview, "Start Quartus compilation.....\n");
663
                my @compilation_command =(
664
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status' ",
665
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status' ",
666
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status' ",
667
                        "cd \"$target_dir/\" \n xterm -e sh -c '$Quartus_bin/quartus_sta --64bit $name;echo \$? > status' ");
668
 
669
                foreach my $cmd (@compilation_command){
670
                        add_info(\$tview,"$cmd\n");
671
                        unlink "$target_dir/status";
672
                        my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout( $cmd);
673
                        open(my $fh,  "<$target_dir/status") || die "Can not open: $!";
674
                        read($fh,my $status,1);
675
                        close($fh);
676
                        if("$status" != "0"){
677
                                ($stdout,$exit)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/output_files/\" \n grep -h \"Error (\" *");
678
                                add_colored_info(\$tview,"$stdout\n Quartus compilation failed !\n",'red');
679
                                $error=1;
680
                                last;
681
                        }
682
                }
683
                add_colored_info(\$tview,"Quartus compilation is done successfully in $target_dir!\n", 'blue') if($error==0);
684
 
685
 
686
        });
687
 
688
 
689
 
690
 
691
 
692
 
693
 
694
 
695
}
696
 
697
 
698
 
699
 
700
 
701
 
702
sub modelsim_compilation{
703
        my ($self,$name,$top,$target_dir)=@_;
704
        #my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
705
 
706
 
707
        my $run=def_image_button('icons/run.png','run');
708
        my $back=def_image_button('icons/left.png','Previous');
709
        my $regen=def_image_button('icons/refresh.png','Regenerate testbench.v');
710
        #create testbench.v
711
        gen_modelsim_soc_testbench ($self,$name,$top,$target_dir) if ((-f "$target_dir/src_verilog/testbench.v")==0);
712
 
713
 
714
 
715
        my ($app,$table,$tview,$window) = software_main("$target_dir/src_verilog",'testbench.v');
716
        $table->attach($back,1,2,1,2,'shrink','shrink',2,2);
717
        $table->attach($regen,4,5,1,2,'shrink','shrink',2,2);
718
        $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
719
 
720
 
721
 
722
        $regen-> signal_connect("clicked" => sub{
723
                my $dialog = Gtk2::MessageDialog->new (my $window,
724
                                      'destroy-with-parent',
725
                                      'question', # message type
726
                                      'yes-no', # which set of buttons?
727
                                      "Are you sure you want to regenaret the testbench.v file? Note that any changes you have made will be lost");
728
                my $response = $dialog->run;
729
                if ($response eq 'yes') {
730
                        gen_modelsim_soc_testbench ($self,$name,$top,$target_dir);
731
                        $app->load_source("$target_dir/src_verilog/testbench.v");
732
                }
733
                $dialog->destroy;
734
 
735
        });
736
 
737
 
738
 
739
 
740
 
741
 
742
        $back-> signal_connect("clicked" => sub{
743
 
744
                $window->destroy;
745
                select_compiler($self,$name,$top,$target_dir);
746
 
747
        });
748
 
749
 
750
        #creat modelsim dir
751
        add_info(\$tview,"creat Modelsim dir in $target_dir\n");
752
        my $model="$target_dir/Modelsim";
753
        rmtree("$model");
754
        mkpath("$model/rtl_work",1,01777);
755
 
756
        #create modelsim.tcl file
757
my $tcl="#!/usr/bin/tclsh
758
 
759
 
760
transcript on
761
if {[file exists rtl_work]} {
762
        vdel -lib rtl_work -all
763
}
764
vlib rtl_work
765
vmap work rtl_work
766
";
767
 
768
#Get the list of  all verilog files in src_verilog folder
769
        add_info(\$tview,"Get the list of all verilog files in src_verilog folder\n");
770
        my @files = File::Find::Rule->file()
771
                ->name( '*.v','*.V','*.sv' )
772
                ->in( "$target_dir/src_verilog" );
773
#make sure source files have key word 'module' 
774
        my @sources;
775
        foreach my $p (@files){
776
                my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
777
                if(check_file_has_string($p,'module')){
778
                        if ($suffix eq ".sv"){$tcl=$tcl."vlog -sv -work work +incdir+$path \{$p\}\n";}
779
                        else {$tcl=$tcl."vlog -vlog01compat -work work +incdir+$path \{$p\}\n";}
780
                }
781
        }
782
 
783
$tcl="$tcl
784
vsim -t 1ps  -L rtl_work -L work -voptargs=\"+acc\"  testbench
785
 
786
add wave *
787
view structure
788
view signals
789
run -all
790
";
791
 
792
        save_file ("$model/run.tcl",$tcl);
793
        $run -> signal_connect("clicked" => sub{
794
                set_gui_status($self,'save_project',1);
795
                $app->do_save();
796
                my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin');
797
                my $cmd="cd $target_dir; $modelsim_bin/vsim -do $model/run.tcl";
798
                my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
799
                if(length $stderr>1){
800
                        add_info(\$tview,"$stderr\n");
801
                }else {
802
                        add_info(\$tview,"$stdout\n");
803
                }
804
 
805
        });
806
 
807
        #$window->show_all();
808
}
809
 
810
 
811
 
812
 
813
sub verilator_compilation {
814
        my ($self,$name,$top,$target_dir)=@_;
815
        my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
816
        my $mtable = def_table(10, 10, FALSE);
817
        my ($outbox,$outtext)= create_text();
818
        add_colored_tag($outtext,'red');
819
        add_colored_tag($outtext,'blue');
820
        my $next=def_image_button('icons/run.png','Next');
821
        my $back=def_image_button('icons/left.png','Previous');
822
 
823
 
824
        $mtable->attach_defaults ($outbox ,0, 10, 4,9);
825
        $mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
826
        $mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
827
 
828
 
829
 
830
        $back-> signal_connect("clicked" => sub{
831
 
832
                $window->destroy;
833
                select_compiler($self,$name,$top,$target_dir);
834
 
835
        });
836
        $next-> signal_connect("clicked" => sub{
837
 
838
                $window->destroy;
839
                verilator_testbench($self,$name,$top,$target_dir);
840
 
841
        });
842
 
843
        #creat verilator dir
844
        add_info(\$outtext,"creat verilator dir in $target_dir\n");
845
        my $verilator="$target_dir/verilator";
846
        rmtree("$verilator/rtl_work");
847
        rmtree("$verilator/processed_rtl");
848
        mkpath("$verilator/rtl_work/",1,01777);
849
        mkpath("$verilator/processed_rtl/",1,01777);
850
 
851
 
852
        #copy all verilog files in rtl_work folder
853
        add_info(\$outtext,"Copy all verilog files in rtl_work folder\n");
854
        my @files = File::Find::Rule->file()
855
                ->name( '*.v','*.V','*.sv' )
856
                ->in( "$target_dir/src_verilog" );
857
        foreach my $file (@files) {
858
                copy($file,"$verilator/rtl_work/");
859
        }
860
 
861
        #"split all verilog modules in separate  files"
862
        add_info(\$outtext,"split all verilog modules in separate files\n");
863
        my $split = Verilog::EditFiles->new
864
        (outdir => "$verilator/processed_rtl",
865
        translate_synthesis => 0,
866
        celldefine => 0,
867
        );
868
        $split->read_and_split(glob("$verilator/rtl_work/*.v"));
869
        $split->read_and_split(glob("$verilator/rtl_work/*.sv"));
870
        $split->write_files();
871
 
872
        #run verilator
873
        #my $cmd= "cd \"$verilator/processed_rtl\" \n xterm -e sh -c ' verilator  --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3  -CFLAGS -O3'";
874
        my $cmd= "cd \"$verilator/processed_rtl\" \n  verilator  --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3  -CFLAGS -O3";
875
        add_info(\$outtext,"$cmd\n");
876
        my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
877
        if(length $stderr>1){
878
                add_info(\$outtext,"$stderr\n");
879
        }else {
880
                add_info(\$outtext,"$stdout\n");
881
        }
882
 
883
        #check if verilator model has been generated 
884
        if (-f "$verilator/processed_rtl/obj_dir/Vtop.cpp"){
885
                add_colored_info(\$outtext,"Veriator model has been generated successfully!",'blue');
886
        }else {
887
                add_colored_info(\$outtext,"Verilator compilation failed!\n","red");
888
                $next->destroy();
889
        }
890
 
891
 
892
 
893
 
894
        $window->add ($mtable);
895
        $window->show_all();
896
 
897
 
898
 
899
}
900
 
901
sub gen_verilator_soc_testbench {
902
        my ($self,$name,$top,$target_dir)=@_;
903
        my $verilator="$target_dir/verilator";
904
        my $dir="$verilator/";
905
        my $soc_top= $self->soc_get_top ();
906
        my @intfcs=$soc_top->top_get_intfc_list();
907
        my %PP;
908
        my $top_port_info="IO type\t  port_size\t  port_name\n";
909
        foreach my $intfc (@intfcs){
910
                my $key= ( $intfc eq 'plug:clk[0]')? 'clk' :
911
                         ( $intfc eq 'plug:reset[0]')? 'reset':
912
                         ( $intfc eq 'plug:enable[0]')? 'en' : 'other';
913
                my $key1="${key}1";
914
                my $key0="${key}0";
915
 
916
                my @ports=$soc_top->top_get_intfc_ports_list($intfc);
917
                foreach my $p (@ports){
918
                        my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
919
                        $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} top->$p=1;\n" : "top->$p=1;\n";
920
                        $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} top->$p=0;\n" : "top->$p=0;\n";
921
                        $top_port_info="$top_port_info $type  $range  top->$p \n";
922
                }
923
 
924
 
925
        }
926
        my $main_c=get_license_header("testbench.cpp");
927
$main_c="$main_c
928
#include <stdlib.h>
929
#include <stdio.h>
930
#include <unistd.h>
931
#include <string.h>
932
#include <verilated.h>          // Defines common routines
933
#include \"Vtop.h\"               // From Verilating \"$name.v\" file
934
 
935
Vtop                    *top;
936
/*
937
$top_port_info
938
*/
939
 
940
int reset,clk;
941
unsigned int main_time = 0; // Current simulation time
942
 
943
int main(int argc, char** argv) {
944
        Verilated::commandArgs(argc, argv);   // Remember args
945
        top     = new Vtop;
946
 
947
        /********************
948
        *       initialize input
949
        *********************/
950
 
951
        $PP{reset1}
952
        $PP{en1}
953
        main_time=0;
954
        printf(\"Start Simulation\\n\");
955
        while (!Verilated::gotFinish()) {
956
 
957
                if (main_time >= 10 ) {
958
                        $PP{reset0}
959
                }
960
 
961
 
962
                if ((main_time & 1) == 0) {
963
                        $PP{clk1}      // Toggle clock
964
                        // you can change the inputs and read the outputs here in case they are captured at posedge of clock
965
 
966
 
967
 
968
                }//if
969
                else
970
                {
971
                        $PP{clk0}
972
 
973
 
974
 
975
                }//else
976
 
977
 
978
                main_time ++;
979
                top->eval();
980
                }
981
        top->final();
982
}
983
 
984
double sc_time_stamp () {       // Called by \$time in Verilog
985
        return main_time;
986
}
987
";
988
        save_file("$dir/testbench.cpp",$main_c);
989
 
990
 
991
 
992
}
993
 
994
 
995
sub gen_modelsim_soc_testbench {
996
        my ($self,$name,$top,$target_dir)=@_;
997
        my $dir="$target_dir/src_verilog";
998
        my $soc_top= $self->object_get_attribute('top_ip',undef);
999
        my @intfcs=$soc_top->top_get_intfc_list();
1000
        my %PP;
1001
        my $top_port_def="// ${name}.v IO definition \n";
1002
        my $pin_assign;
1003
        my $rst_inputs='';
1004
 
1005
        #read port list 
1006
        my $vdb=read_verilog_file($top);
1007
        my %param = $vdb->get_modules_parameters("${name}_top");
1008
 
1009
 
1010
 
1011
 
1012
 
1013
 
1014
        foreach my $intfc (@intfcs){
1015
                my $key= ( $intfc eq 'plug:clk[0]')? 'clk' :
1016
                         ( $intfc eq 'plug:reset[0]')? 'reset':
1017
                         ( $intfc eq 'plug:enable[0]')? 'en' : 'other';
1018
                my $key1="${key}1";
1019
                my $key0="${key}0";
1020
 
1021
                my @ports=$soc_top->top_get_intfc_ports_list($intfc);
1022
                my $f=1;
1023
                foreach my $p (@ports){
1024
                        my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
1025
 
1026
                        $PP{$key1}= (defined $PP{$key1})? "$PP{$key1} $p=1;\n" : "$p=1;\n";
1027
                        $PP{$key0}= (defined $PP{$key0})? "$PP{$key0} $p=0;\n" : "$p=0;\n";
1028
 
1029
 
1030
                        if  (length($range)!=0){
1031
                                #replace parameter with their values            
1032
                                my @a= split (/\b/,$range);
1033
                                foreach my $l (@a){
1034
                                        my $value=$param{$l};
1035
                                        if(defined $value){
1036
                                                chomp $value;
1037
                                                ($range=$range)=~ s/\b$l\b/$value/g      if(defined $param{$l});
1038
                                        }
1039
                                }
1040
                                $range = "[ $range ]" ;
1041
                        }
1042
 
1043
 
1044
 
1045
                        if($type eq 'input'){
1046
                                $top_port_def="$top_port_def  reg  $range  $p;\n"
1047
                        }else{
1048
                                $top_port_def="$top_port_def  wire  $range  $p;\n"
1049
                        }
1050
                        $pin_assign=(defined $pin_assign)? "$pin_assign,\n\t\t.$p($p)":  "\t\t.$p($p)";
1051
                        $rst_inputs= "$rst_inputs $p=0;\n" if ($key eq 'other' && $type eq 'input' );
1052
                }
1053
 
1054
 
1055
        }
1056
 
1057
my $test_v= get_license_header("testbench.v");
1058
 
1059
$test_v ="$test_v
1060
 
1061
`timescale       1ns/1ps
1062
 
1063
module testbench;
1064
 
1065
$top_port_def
1066
 
1067
 
1068
        $name uut (
1069
$pin_assign
1070
        );
1071
 
1072
//clock defination
1073
initial begin
1074
        forever begin
1075
        #5 $PP{clk0}
1076
        #5 $PP{clk1}
1077
        end
1078
end
1079
 
1080
 
1081
 
1082
initial begin
1083
        // reset $name module at the start up
1084
        $PP{reset1}
1085
        $PP{en1}
1086
        $rst_inputs
1087
        // deasert the reset after 200 ns
1088
        #200
1089
        $PP{reset0}
1090
 
1091
        // write your testbench here
1092
 
1093
 
1094
 
1095
 
1096
end
1097
 
1098
endmodule
1099
";
1100
        save_file("$dir/testbench.v",$test_v);
1101
 
1102
 
1103
 
1104
}
1105
 
1106
sub verilator_testbench{
1107
        my ($self,$name,$top,$target_dir)=@_;
1108
        my $verilator="$target_dir/verilator";
1109
        my $dir="$verilator";
1110
        gen_verilator_soc_testbench (@_) if((-f "$dir/testbench.cpp")==0);
1111
        #copy makefile
1112
        copy("../script/verilator_soc_make", "$verilator/processed_rtl/obj_dir/Makefile");
1113
 
1114
 
1115
        my ($app,$table,$tview,$window) = software_main($dir,'testbench.cpp');
1116
 
1117
 
1118
        my $make = def_image_button('icons/gen.png','Compile');
1119
        my $regen=def_image_button('icons/refresh.png','Regenerate Testbench.cpp');
1120
        my $run = def_image_button('icons/run.png','Run');
1121
        my $back=def_image_button('icons/left.png','Previous');
1122
 
1123
        $table->attach ($back,1,2,1,2,'shrink','shrink',0,0);
1124
        $table->attach ($regen,3,4,1,2,'shrink','shrink',0,0);
1125
        $table->attach ($make,7, 8, 1,2,'shrink','shrink',0,0);
1126
        $table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
1127
 
1128
        $back-> signal_connect("clicked" => sub{
1129
 
1130
                $window->destroy;
1131
                verilator_compilation($self,$name,$top,$target_dir);
1132
 
1133
        });
1134
 
1135
        $regen-> signal_connect("clicked" => sub{
1136
                my $dialog = Gtk2::MessageDialog->new (my $window,
1137
                                      'destroy-with-parent',
1138
                                      'question', # message type
1139
                                      'yes-no', # which set of buttons?
1140
                                      "Are you sure you want to regenaret the testbench.cpp file? Note that any changes you have made will be lost");
1141
                my $response = $dialog->run;
1142
                if ($response eq 'yes') {
1143
                        gen_verilator_soc_testbench ($self,$name,$top,$target_dir);
1144
                        $app->load_source("$dir/testbench.cpp");
1145
                }
1146
                $dialog->destroy;
1147
 
1148
        });
1149
 
1150
 
1151
        $make -> signal_connect("clicked" => sub{
1152
                $app->do_save();
1153
                copy("$dir/testbench.cpp", "$verilator/processed_rtl/obj_dir/testbench.cpp");
1154
                run_make_file("$verilator/processed_rtl/obj_dir/",$tview);
1155
 
1156
        });
1157
 
1158
        $run -> signal_connect("clicked" => sub{
1159
                my $bin="$verilator/processed_rtl/obj_dir/testbench";
1160
                if (-f $bin){
1161
                        my $cmd= "cd \"$verilator/processed_rtl/obj_dir/\" \n xterm -e sh -c $bin";
1162
                        add_info(\$tview,"$cmd\n");
1163
                        my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
1164
                        if(length $stderr>1){
1165
                                add_colored_info(\$tview,"$stderr\n",'red');
1166
                        }else {
1167
                                add_info(\$tview,"$stdout\n");
1168
                        }
1169
 
1170
                }else{
1171
                        add_colored_info(\$tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red')
1172
                }
1173
 
1174
                });
1175
 
1176
 
1177
}
1178
 
1179
 
1180
1;

powered by: WebSVN 2.1.0

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