Line 1... |
Line 1... |
#! /usr/bin/perl -w
|
#! /usr/bin/perl -w
|
use Glib qw/TRUE FALSE/;
|
use constant::boolean;
|
use strict;
|
use strict;
|
use warnings;
|
use warnings;
|
|
|
use FindBin;
|
use FindBin;
|
use lib $FindBin::Bin;
|
use lib $FindBin::Bin;
|
Line 14... |
Line 14... |
use File::Copy;
|
use File::Copy;
|
use File::Copy::Recursive qw(dircopy);
|
use File::Copy::Recursive qw(dircopy);
|
use Cwd 'abs_path';
|
use Cwd 'abs_path';
|
use Verilog::EditFiles;
|
use Verilog::EditFiles;
|
|
|
use Gtk2;
|
|
|
|
use List::MoreUtils qw( minmax );
|
use List::MoreUtils qw( minmax );
|
|
|
|
|
|
|
################
|
################
|
# Comile
|
# Compile
|
#################
|
#################
|
|
|
|
|
|
|
sub is_capital_sensitive()
|
sub is_capital_sensitive()
|
Line 33... |
Line 33... |
my ($cell_layout, $cell, $tree_model, $iter, $data) = @_;
|
my ($cell_layout, $cell, $tree_model, $iter, $data) = @_;
|
my $sensitive = !$tree_model->iter_has_child($iter);
|
my $sensitive = !$tree_model->iter_has_child($iter);
|
$cell->set('sensitive', $sensitive);
|
$cell->set('sensitive', $sensitive);
|
}
|
}
|
|
|
sub gen_combo_model{
|
|
my $ref=shift;
|
|
my %inputs=%{$ref};
|
|
my $store = Gtk2::TreeStore->new('Glib::String');
|
|
for my $i (sort { $a cmp $b} keys %inputs ) {
|
|
my $iter = $store->append(undef);
|
|
|
|
$store->set($iter, 0, $i);
|
|
for my $capital (sort { $a cmp $b} keys %{$inputs{$i}}) {
|
|
my $iter2 = $store->append($iter);
|
|
$store->set($iter2, 0, $capital);
|
|
}
|
|
}
|
|
return $store;
|
|
|
|
}
|
|
|
|
sub gen_tree_combo{
|
|
my $model=shift;
|
|
my $combo = Gtk2::ComboBox->new_with_model($model);
|
|
my $renderer = Gtk2::CellRendererText->new();
|
|
$combo->pack_start($renderer, TRUE);
|
|
$combo->set_attributes($renderer, "text", 0);
|
|
$combo->set_cell_data_func($renderer, \&is_capital_sensitive);
|
|
return $combo;
|
|
|
|
}
|
|
|
|
sub get_range {
|
sub get_range {
|
my ($board,$self,$porttype,$assignname,$portrange,$portname) =@_;
|
my ($board,$self,$porttype,$assignname,$portrange,$portname) =@_;
|
my $box= def_hbox(FALSE,0);
|
my $box= def_hbox(FALSE,0);
|
my @range=$board->board_get_pin_range($porttype,$assignname);
|
my @range=$board->board_get_pin_range($porttype,$assignname);
|
Line 203... |
Line 177... |
|
|
|
|
sub select_compiler {
|
sub select_compiler {
|
my ($self,$name,$top,$target_dir,$end_func)=@_;
|
my ($self,$name,$top,$target_dir,$end_func)=@_;
|
my $window = def_popwin_size(40,40,"Step 1: Select Compiler",'percent');
|
my $window = def_popwin_size(40,40,"Step 1: Select Compiler",'percent');
|
#get the list of boards located in "boards/*" folder
|
|
my @dirs = grep {-d} glob("../boards/*");
|
|
my ($fpgas,$init);
|
|
foreach my $dir (@dirs) {
|
|
my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
|
|
$init=$name;
|
|
$fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
|
|
}
|
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
my $col=0;
|
my $col=0;
|
my $row=0;
|
my $row=0;
|
|
|
my $compilers=$self->object_get_attribute('compile','compilers');#"QuartusII,Verilator,Modelsim"
|
my $compilers=$self->object_get_attribute('compile','compilers');#"QuartusII,Vivado,Verilator,Modelsim"
|
|
|
my $compiler=gen_combobox_object ($self,'compile','type',$compilers,"QuartusII",undef,undef);
|
my $compiler=gen_combobox_object ($self,'compile','type',$compilers,"QuartusII",undef,undef);
|
$table->attach(gen_label_in_center("Compiler tool"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$table->attach(gen_label_in_center("Compiler tool"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$table->attach($compiler,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$table->attach($compiler,$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$row++;$col=0;
|
$row++;$col=0;
|
|
|
|
|
|
|
my $old_board_name=$self->object_get_attribute('compile','board');
|
my $old_board_name=$self->object_get_attribute('compile','board');
|
my $old_compiler=$self->object_get_attribute('compile','type');
|
my $old_compiler=$self->object_get_attribute('compile','type');
|
my $compiler_options = ($old_compiler eq "QuartusII")? select_board ($self,$name,$top,$target_dir):
|
my $vendor= ($old_compiler eq "QuartusII")? 'Altera' : 'Xilinx';
|
|
|
|
#get the list of boards located in "boards/*" folder
|
|
my @dirs = grep {-d} glob("../boards/$vendor/*");
|
|
my ($fpgas,$init);
|
|
foreach my $dir (@dirs) {
|
|
my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
|
|
$init=$name;
|
|
$fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
|
|
}
|
|
|
|
|
|
my $compiler_options =
|
|
($old_compiler eq "QuartusII")? select_board ($self,$name,$top,$target_dir,$vendor):
|
|
($old_compiler eq "Vivado" )? select_board ($self,$name,$top,$target_dir,$vendor):
|
($old_compiler eq "Modelsim")? select_model_path ($self,$name,$top,$target_dir):
|
($old_compiler eq "Modelsim")? select_model_path ($self,$name,$top,$target_dir):
|
|
($old_compiler eq "Verilator")? select_parallel_process_num ($self,$name,$top,$target_dir):
|
gen_label_in_center(" ");
|
gen_label_in_center(" ");
|
|
|
$table->attach($compiler_options,$col,$col+2,$row,$row+1,'fill','shrink',2,2); $row++;
|
$table->attach($compiler_options,$col,$col+2,$row,$row+1,'fill','shrink',2,2); $row++;
|
|
|
$col=1;
|
$col=1;
|
my $i;
|
my $i;
|
for ($i=$row; $i<5; $i++){
|
for ($i=$row; $i<5; $i++){
|
Line 243... |
Line 224... |
$row=$i;
|
$row=$i;
|
|
|
|
|
$window->add ($table);
|
$window->add ($table);
|
$window->show_all();
|
$window->show_all();
|
my $next=def_image_button('icons/right.png','Next');
|
my $next=def_image_button('icons/right.png','_Next',FALSE,1);
|
$table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++;
|
$table->attach($next,$col,$col+1,$row,$row+1,'shrink','shrink',2,2);$col++;
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
my $compiler_type=$self->object_get_attribute('compile','type');
|
my $compiler_type=$self->object_get_attribute('compile','type');
|
if($compiler_type eq "QuartusII"){
|
if($compiler_type eq "QuartusII" || $compiler_type eq "Vivado"){
|
|
$vendor= ($compiler_type eq "QuartusII")? 'Altera' : 'Xilinx';
|
my $new_board_name=$self->object_get_attribute('compile','board');
|
my $new_board_name=$self->object_get_attribute('compile','board');
|
if(defined $old_board_name) {
|
if(defined $old_board_name) {
|
if ($old_board_name ne $new_board_name){
|
if ($old_board_name ne $new_board_name){
|
remove_pin_assignment($self);
|
remove_pin_assignment($self);
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
Line 265... |
Line 247... |
my $board_top_file= "$fpath/Top.v";
|
my $board_top_file= "$fpath/Top.v";
|
unlink $board_top_file if ($old_board_name ne $new_board_name);
|
unlink $board_top_file if ($old_board_name ne $new_board_name);
|
|
|
|
|
}
|
}
|
if($new_board_name eq "Add New Board") {add_new_fpga_board($self,$name,$top,$target_dir,$end_func);}
|
if($new_board_name eq "Add New Board") {add_new_fpga_board($self,$name,$top,$target_dir,$end_func,$vendor);}
|
else {get_pin_assignment($self,$name,$top,$target_dir,$end_func);}
|
else {get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);}
|
}elsif($compiler_type eq "Modelsim"){
|
}
|
modelsim_compilation($self,$name,$top,$target_dir);
|
|
|
|
|
|
|
|
|
|
|
|
|
elsif($compiler_type eq "Modelsim"){
|
|
modelsim_compilation($self,$name,$top,$target_dir,$vendor);
|
|
|
}else{#verilator
|
}else{#verilator
|
verilator_compilation_win($self,$name,$top,$target_dir);
|
verilator_compilation_win($self,$name,$top,$target_dir,$vendor);
|
|
|
}
|
}
|
|
|
$window->destroy;
|
$window->destroy;
|
|
|
});
|
});
|
|
|
$compiler->signal_connect("changed" => sub{
|
$compiler->signal_connect("changed" => sub{
|
$compiler_options->destroy;
|
$compiler_options->destroy;
|
my $new_board_name=$self->object_get_attribute('compile','type');
|
my $new_board_name=$self->object_get_attribute('compile','type');
|
$compiler_options = ($new_board_name eq "QuartusII")? select_board ($self,$name,$top,$target_dir):
|
$compiler_options =
|
|
($new_board_name eq "QuartusII")? select_board ($self,$name,$top,$target_dir,"Altera"):
|
|
($new_board_name eq "Vivado")? select_board ($self,$name,$top,$target_dir,"Xilinx"):
|
($new_board_name eq "Modelsim")? select_model_path ($self,$name,$top,$target_dir):
|
($new_board_name eq "Modelsim")? select_model_path ($self,$name,$top,$target_dir):
|
|
($new_board_name eq "Verilator")? select_parallel_process_num ($self,$name,$top,$target_dir):
|
gen_label_in_center(" ");
|
gen_label_in_center(" ");
|
$table->attach($compiler_options,0,2,1,2,'fill','shrink',2,2);
|
$table->attach($compiler_options,0,2,1,2,'fill','shrink',2,2);
|
$table->show_all;
|
$table->show_all;
|
|
|
});
|
});
|
Line 296... |
Line 288... |
|
|
|
|
|
|
|
|
|
|
|
|
sub select_board {
|
sub select_board {
|
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
|
|
#get the list of boards located in "boards/*" folder
|
#get the list of boards located in "boards/*" folder
|
my @dirs = grep {-d} glob("../boards/*");
|
my @dirs = grep {-d} glob("../boards/$vendor/*");
|
my ($fpgas,$init);
|
my ($fpgas,$init);
|
$fpgas="Add New Board";
|
$fpgas="Add New Board";
|
|
|
foreach my $dir (@dirs) {
|
foreach my $dir (@dirs) {
|
my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
|
my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
|
Line 313... |
Line 306... |
$init="$name";
|
$init="$name";
|
}
|
}
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
my $col=0;
|
my $col=0;
|
my $row=0;
|
my $row=0;
|
|
my $compiler = ($vendor eq "Altera")? 'quartus' : 'vivado';
|
|
my $bin_name = "$compiler bin";
|
|
my $env = ($vendor eq "Altera")? "QUARTUS_BIN" : "VIVADO_BIN";
|
|
my $Fpga_bin= $ENV{$env};
|
|
|
my $old_board_name=$self->object_get_attribute('compile','board');
|
my $old_board_name=$self->object_get_attribute('compile','board');
|
$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++;
|
$table->attach(gen_label_help("The list of supported boards are obtained from \"mpsoc/boards/$vendor\" path. You can add your boards by adding its required files in aformentioned path. Note that currently Altera and Xilinx FPGAs are supported.",'Targeted Board:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$table->attach(gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
|
$table->attach(gen_combobox_object ($self,'compile','board',$fpgas,$init,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
|
|
my $bin = $self->object_get_attribute('compile',$bin_name);
|
|
|
my $bin = $self->object_get_attribute('compile','quartus_bin');
|
|
my $Quartus_bin= $ENV{QUARTUS_BIN};
|
|
$col=0;
|
$col=0;
|
$self->object_add_attribute('compile','quartus_bin',$ENV{QUARTUS_BIN}) if (!defined $bin && defined $Quartus_bin);
|
$self->object_add_attribute('compile',$bin_name,$Fpga_bin) if (!defined $bin && defined $Fpga_bin);
|
$table->attach(gen_label_help("Path to quartus/bin directory. You can set a default path as QUARTUS_BIN envirement variable in ~/.bashrc file.
|
$table->attach(gen_label_help("Path to $vendor/bin directory. You can set a default path as $env environment variable in ~/.bashrc file.
|
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++;
|
e.g: export $env=/home/alireza/$compiler/bin","$env:"),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$table->attach(get_dir_in_object ($self,'compile','quartus_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
|
$table->attach(get_dir_in_object ($self,'compile',$bin_name,undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
|
|
|
|
|
|
|
|
|
|
|
return $table;
|
return $table;
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
sub select_model_path {
|
sub select_model_path {
|
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir)=@_;
|
|
|
|
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
Line 346... |
Line 348... |
|
|
my $bin = $self->object_get_attribute('compile','modelsim_bin');
|
my $bin = $self->object_get_attribute('compile','modelsim_bin');
|
my $modelsim_bin= $ENV{MODELSIM_BIN};
|
my $modelsim_bin= $ENV{MODELSIM_BIN};
|
$col=0;
|
$col=0;
|
$self->object_add_attribute('compile','modelsim_bin',$modelsim_bin) if (!defined $bin && defined $modelsim_bin);
|
$self->object_add_attribute('compile','modelsim_bin',$modelsim_bin) if (!defined $bin && defined $modelsim_bin);
|
$table->attach(gen_label_help("Path to modelsim/bin directory. You can set a default path as MODELSIM_BIN envirement variable in ~/.bashrc file.
|
$table->attach(gen_label_help("Path to modelsim/bin directory. You can set a default path as MODELSIM_BIN environment variable in ~/.bashrc file.
|
e.g. export MODELSIM_BIN=/home/alireza/altera/modeltech/bin",'Modelsim bin:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
e.g. export MODELSIM_BIN=/home/alireza/altera/modeltech/bin",'Modelsim bin:'),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$col++;
|
$table->attach(get_dir_in_object ($self,'compile','modelsim_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
|
$table->attach(get_dir_in_object ($self,'compile','modelsim_bin',undef,undef,undef),$col,$col+1,$row,$row+1,'fill','shrink',2,2);$row++;
|
|
|
return $table;
|
return $table;
|
|
|
}
|
}
|
|
|
|
|
|
sub select_parallel_process_num {
|
|
my ($self,$name,$top,$target_dir)=@_;
|
|
my $table = def_table(2, 2, FALSE);
|
|
my $col=0;
|
|
my $row=0;
|
|
|
|
#get total number of processor in the system
|
|
my $cmd = "nproc\n";
|
|
my $cpu_num=4;
|
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
|
if(length $stderr>1){
|
|
#nproc command has failed. set default 4 paralel processor
|
|
|
|
}else {
|
|
my ($number ) = $stdout =~ /(\d+)/;
|
|
if (defined $number ){
|
|
$cpu_num =$number if ($number > 0 );
|
|
}
|
|
}
|
|
($row,$col)= add_param_widget ($self,"Paralle run:" , "cpu_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of processors the Verilator can use at once to run parallel compilations/simulations", $table,$row,$col,1, 'compile', undef,undef,'vertical');
|
|
return $table;
|
|
}
|
|
sub select_parallel_thread_num {
|
|
my ($self,$name,$top,$target_dir)=@_;
|
|
my $table = def_table(2, 2, FALSE);
|
|
my $col=0;
|
|
my $row=0;
|
|
|
|
#get total number of processor in the system
|
|
my $cmd = "nproc\n";
|
|
my $cpu_num=4;
|
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
|
if(length $stderr>1){
|
|
#nproc command has failed. set default 4 paralel processor
|
|
|
|
}else {
|
|
my ($number ) = $stdout =~ /(\d+)/;
|
|
if (defined $number ){
|
|
$cpu_num =$number if ($number > 0 );
|
|
}
|
|
}
|
|
($row,$col)= add_param_widget ($self,"Thread run:" , "thread_num", 1, 'Spin-button', "1,$cpu_num,1","specify the number of threads the Verilator can use at once in one simulation", $table,$row,$col,1, 'compile', undef,undef,'vertical');
|
|
return $table;
|
|
}
|
|
|
|
|
|
|
|
|
sub remove_pin_assignment{
|
sub remove_pin_assignment{
|
my $self=shift;
|
my $self=shift;
|
$self->object_remove_attribute('compile_pin_pos');
|
$self->object_remove_attribute('compile_pin_pos');
|
$self->object_remove_attribute('compile_pin');
|
$self->object_remove_attribute('compile_pin');
|
$self->object_remove_attribute('compile_assign_type');
|
$self->object_remove_attribute('compile_assign_type');
|
Line 366... |
Line 416... |
$self->object_remove_attribute('compile_pin_range_lsb');
|
$self->object_remove_attribute('compile_pin_range_lsb');
|
}
|
}
|
|
|
|
|
|
|
|
sub add_new_fpga_board{
|
|
|
|
my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
|
|
sub add_new_fpga_board{
|
my $window = def_popwin_size(50,80,"Add New $vendor FPGA Board",'percent');
|
my ($self,$name,$top,$target_dir,$end_func)=@_;
|
|
my $window = def_popwin_size(50,80,"Add New FPGA Board",'percent');
|
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef);
|
my $scrolled_win=add_widget_to_scrolled_win($table);
|
$scrolled_win->set_policy( "automatic", "automatic" );
|
|
$scrolled_win->add_with_viewport($table);
|
|
|
|
|
|
my $mtable = def_table(10, 10, FALSE);
|
my $mtable = def_table(10, 10, FALSE);
|
|
|
my $next=def_image_button('icons/plus.png','Add');
|
my $next=def_image_button('icons/plus.png','Add');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $auto=def_image_button('icons/advance.png','Auto-fill');
|
|
|
|
$mtable->attach_defaults($scrolled_win,0,10,0,9);
|
$mtable->attach_defaults($scrolled_win,0,10,0,9);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2) if (defined $name);
|
$mtable->attach($auto,5,6,9,10,'shrink','shrink',2,2);
|
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
|
|
set_tip($auto, "Auto-fill JTAG configuration. The board must be powered on and be connecred to the PC.");
|
|
|
my ($Twin,$tview)=create_txview();
|
|
|
|
|
|
my $widgets=
|
|
($vendor eq 'Altera')? add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor):
|
|
add_new_xilinx_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor,$tview);
|
|
|
my $widgets= add_new_fpga_board_widgets($self,$name,$top,$target_dir,$end_func);
|
|
my ($Twin,$tview)=create_text();
|
|
|
|
|
|
my $v1=gen_vpaned($widgets,0.3,$Twin);
|
my $v1=gen_vpaned($widgets,0.3,$Twin);
|
|
|
$table->attach_defaults($v1,0,3,0,2);
|
$table->attach_defaults($v1,0,3,0,2);
|
Line 412... |
Line 459... |
select_compiler($self,$name,$top,$target_dir,$end_func);
|
select_compiler($self,$name,$top,$target_dir,$end_func);
|
|
|
});
|
});
|
|
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
my $result = add_new_fpga_board_files($self);
|
my $result = ($vendor eq 'Altera')?
|
if(! defined $result ){
|
add_new_altera_fpga_board_files($self,$vendor):
|
select_compiler($self,$name,$top,$target_dir,$end_func);
|
add_new_xilinx_fpga_board_files($self,$vendor);
|
message_dialog("The new board has been added successfully!");
|
|
|
|
|
if(! defined $result ){
|
|
select_compiler($self,$name,$top,$target_dir,$end_func) if (defined $name);
|
$window->destroy;
|
$window->destroy;
|
|
message_dialog("The new board has been added successfully!");
|
}else {
|
}else {
|
show_info(\$tview," ");
|
show_info($tview," ");
|
show_colored_info(\$tview,$result,'red');
|
show_colored_info($tview,$result,'red');
|
|
|
}
|
}
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
if($vendor eq 'Altera'){
|
|
my $auto=def_image_button('icons/advance.png','Auto-fill');
|
|
set_tip($auto, "Auto-fill JTAG configuration. The board must be powered on and be connected to the PC.");
|
|
$mtable->attach($auto,5,6,9,10,'shrink','shrink',2,2);
|
$auto-> signal_connect("clicked" => sub{
|
$auto-> signal_connect("clicked" => sub{
|
my $pid;
|
my $pid;
|
my $hw;
|
my $hw;
|
my $dir = Cwd::getcwd();
|
|
my $project_dir = abs_path("$dir/../../"); #mpsoc directory address
|
my $project_dir = get_project_dir();
|
my $command= "$project_dir/mpsoc/src_c/jtag/jtag_libusb/list_usb_dev";
|
my $command= "$project_dir/mpsoc/src_c/jtag/jtag_libusb/list_usb_dev";
|
add_info(\$tview,"$command\n");
|
add_info($tview,"$command\n");
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
|
if(length $stderr>1){
|
if(length $stderr>1){
|
add_colored_info(\$tview,"$stderr\n",'red');
|
add_colored_info($tview,"$stderr\n",'red');
|
add_colored_info(\$tview,"$command was not run successfully!\n",'red');
|
add_colored_info($tview,"$command was not run successfully!\n",'red');
|
}else {
|
}else {
|
|
|
if($exit){
|
if($exit){
|
add_colored_info(\$tview,"$stdout\n",'red');
|
add_colored_info($tview,"$stdout\n",'red');
|
add_colored_info(\$tview,"$command was not run successfully!\n",'red');
|
add_colored_info($tview,"$command was not run successfully!\n",'red');
|
}else{
|
}else{
|
add_info(\$tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
my @a=split /vid=9fb/, $stdout;
|
my @a=split /vid=9fb/, $stdout;
|
if(defined $a[1]){
|
if(defined $a[1]){
|
my @b=split /pid=/, $a[1];
|
my @b=split /pid=/, $a[1];
|
my @c=split /\n/, $b[1];
|
my @c=split /\n/, $b[1];
|
$pid=$c[0];
|
$pid=$c[0];
|
$self->object_add_attribute('compile','quartus_pid',$pid);
|
$self->object_add_attribute('compile','quartus_pid',$pid);
|
add_colored_info(\$tview,"Detected PID: $pid\n",'blue');
|
add_colored_info($tview,"Detected PID: $pid\n",'blue');
|
|
|
}else{
|
}else{
|
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');
|
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');
|
return;
|
return;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
$command= "$ENV{QUARTUS_BIN}/jtagconfig";
|
$command= "$ENV{QUARTUS_BIN}/jtagconfig";
|
add_info(\$tview,"$command\n");
|
add_info($tview,"$command\n");
|
($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
|
($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
|
if(length $stderr>1){
|
if(length $stderr>1){
|
add_colored_info(\$tview,"$stderr\n",'red');
|
add_colored_info($tview,"$stderr\n",'red');
|
add_colored_info(\$tview,"$command was not run successfully!\n",'red');
|
add_colored_info($tview,"$command was not run successfully!\n",'red');
|
}else {
|
}else {
|
|
|
if($exit){
|
if($exit){
|
add_colored_info(\$tview,"$stdout\n",'red');
|
add_colored_info($tview,"$stdout\n",'red');
|
add_colored_info(\$tview,"$command was not run successfully!\n",'red');
|
add_colored_info($tview,"$command was not run successfully!\n",'red');
|
}else{
|
}else{
|
add_info(\$tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
my @a=split /1\)\s+/, $stdout;
|
my @a=split /1\)\s+/, $stdout;
|
if(defined $a[1]){
|
if(defined $a[1]){
|
my @b=split /\s+/, $a[1];
|
my @b=split /\s+/, $a[1];
|
$hw=$b[0];
|
$hw=$b[0];
|
$self->object_add_attribute('compile','quartus_hardware',$hw);
|
$self->object_add_attribute('compile','quartus_hardware',$hw);
|
add_colored_info(\$tview,"Detected Hardware: $hw\n",'blue');
|
add_colored_info($tview,"Detected Hardware: $hw\n",'blue');
|
my $qsf=$self->object_get_attribute('compile','quartus_qsf');
|
my $qsf=$self->object_get_attribute('compile','board_confg_file');
|
if(!defined $qsf ){
|
if(!defined $qsf ){
|
add_colored_info (\$tview,"Cannot detect devce location in JTAG chin. Please enter the QSF file or fill in manually \n",'red');
|
add_colored_info ($tview,"Cannot detect device location in JTAG chin. Please enter the QSF file or fill in manually \n",'red');
|
|
|
}else{
|
}else{
|
#search for device nam ein qsf file
|
#search for device nam ein qsf file
|
$qsf=add_project_dir_to_addr($qsf);
|
$qsf=add_project_dir_to_addr($qsf);
|
if (!(-f $qsf)){
|
if (!(-f $qsf)){
|
add_colored_info (\$tview, "Error Could not find $qsf file!\n");
|
add_colored_info($tview, "Error Could not find $qsf file!\n");
|
return;
|
return;
|
}
|
}
|
my $str=load_file($qsf);
|
my $str=load_file($qsf);
|
my $dw= capture_string_between(' DEVICE ',$str,"\n");
|
my $dw= capture_string_between(' DEVICE ',$str,"\n");
|
if(defined $dw){
|
if(defined $dw){
|
add_colored_info(\$tview,"Device name in qsf file is: $dw\n",'blue');
|
add_colored_info($tview,"Device name in qsf file is: $dw\n",'blue');
|
@b=split /\n/, $a[1];
|
@b=split /\n/, $a[1];
|
|
|
#capture device name in JTAG chain
|
#capture device name in JTAG chain
|
my @f=(0);
|
my @f=(0);
|
foreach my $c (@b){
|
foreach my $c (@b){
|
Line 508... |
Line 559... |
push(@f,$e[2]) if(defined $e[2]);
|
push(@f,$e[2]) if(defined $e[2]);
|
}
|
}
|
|
|
my $pos=find_the_most_similar_position($dw ,@f);
|
my $pos=find_the_most_similar_position($dw ,@f);
|
$self->object_add_attribute('compile','quartus_device',$pos);
|
$self->object_add_attribute('compile','quartus_device',$pos);
|
add_colored_info(\$tview,"$dw has the most similarity with $f[$pos] in JTAG chain\n",'blue');
|
add_colored_info($tview,"$dw has the most similarity with $f[$pos] in JTAG chain\n",'blue');
|
|
|
|
|
}else{
|
}else{
|
add_colored_info (\$tview, "Could not find device name in the $qsf file!\n");
|
add_colored_info ($tview, "Could not find device name in the $qsf file!\n");
|
}
|
}
|
|
|
}
|
}
|
|
|
|
|
}else{
|
}else{
|
#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');
|
#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');
|
|
|
}
|
}
|
|
|
}
|
}
|
}
|
}
|
$widgets->destroy();
|
$widgets->destroy();
|
$widgets= add_new_fpga_board_widgets($self,$name,$top,$target_dir,$end_func);
|
$widgets= add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor);
|
$v1-> pack1($widgets, TRUE, TRUE);
|
$v1-> pack1($widgets, TRUE, TRUE);
|
#$table->attach_defaults($widgets,0,3,0,1);
|
#$table->attach_defaults($widgets,0,3,0,1);
|
$table->show_all();
|
$table->show_all();
|
# my $cmd=" $ENV{'QUARTUS_BIN'}"
|
# my $cmd=" $ENV{'QUARTUS_BIN'}"
|
|
|
});
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
$window->add ($mtable);
|
$window->add ($mtable);
|
$window->show_all();
|
$window->show_all();
|
|
|
}
|
}
|
|
|
|
|
|
|
|
sub add_new_xilinx_fpga_board_widgets{
|
|
my ($self,$name,$top,$target_dir,$end_func,$vendor,$tview)=@_;
|
|
my $table = def_table(2, 2, FALSE);
|
|
|
sub add_new_fpga_board_widgets{
|
my $col=0;
|
my ($self,$name,$top,$target_dir,$end_func)=@_;
|
my $row=0;
|
|
|
|
my $help1="Your given FPGA Board name. Do not use any space in given name";
|
|
my $help2="Path to FPGA board xdc file. In your Xilinx board installation CD or in the Internet, search for a xdc file containing your FPGA device pin assignment constrain).";
|
|
my $help3="Path to FPGA_board_top.v file. A Verilog file containing all your FPGA device IO ports.";
|
|
my $help4="Your Board name (Board PART) e.g. digilentinc.com:arty-z7-20:part0:1.0";
|
|
my $help5="Your FPGA device name (PART) e.g. xc7z020clg400-1 ";
|
|
my $help6="The order number of target device in jtag chain. Run jtag targets after \"connect\" command in xsct terminal to list all available targets.";
|
|
my $help7="Path to Vivado board files repository. E.g download the repo from https://github.com/Digilent/vivado-boards and save in \$ProNoC_work/toolchain/board_files folder.";
|
|
my $help8="Hardware device name e.g. xc7z020_1. To find it you can connect your FPGA board to your PC. In tcl terminal run
|
|
open_hw
|
|
connect_hw_server
|
|
open_hw_target
|
|
get_hw_devices
|
|
It supposed to show the list of your hardware devices in your FPGA. Select the name represent your FPGA device
|
|
";
|
|
|
|
|
|
my $repo ="$ENV{PRONOC_WORK}/toolchain/board_files";
|
|
|
|
|
|
$row++;
|
|
|
|
my @info = (
|
|
{ label=>"FPGA board display name:", param_name=>'fpga_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef},
|
|
{ label=>"Set board repo:", param_name=>'fpga_board_repo', type=>"DIR_path", default_val=>"$repo", content=>undef, info=>$help7, param_parent=>'compile',ref_delay=>undef},
|
|
{ label=>"FPGA board part name:", param_name=>'fpga_board_part', type=>"EntryCombo",default_val=>undef, content=>undef, info =>$help4, param_parent=>'compile', ref_delay=> undef},
|
|
{ label=>"FPGA part name:", param_name=>'fpga_part', type=>"Entry", default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef},
|
|
{ label=>"FPGA Hardware device name:", param_name=>'fpga_hw_device', type=>"EntryCombo", default_val=>undef, content=>undef, info=>$help8, param_parent=>'compile', ref_delay=> undef},
|
|
{ label=>"Target device JTAG chain order number", param_name=>'fpga_board_order', type=>"Spin-button", default_val=>1, content=>"0,256,1", info=>$help6, param_parent=>'compile',ref_delay=>undef},
|
|
{ label=>'FPGA board xdc file:', param_name=>'board_confg_file', type=>"FILE_path", default_val=>undef, content=>"xdc", info=>$help2, param_parent=>'compile', ref_delay=>undef},
|
|
{ label=>"FPGA board golden top Verilog file", param_name=>'fpga_board_v', type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef},
|
|
);
|
|
my %widgets;
|
|
my %rows;
|
|
foreach my $d (@info) {
|
|
$rows{$d->{param_name}} =$row;
|
|
($row,$col,$widgets{$d->{param_name}})=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');
|
|
}
|
|
|
|
my $icon = 'icons/advance.png';
|
|
my $search=def_image_button($icon,undef);
|
|
my $search_board=def_image_button ($icon,undef);
|
|
my $search_dev=def_image_button ($icon,undef);
|
|
my $search_chain=def_image_button ($icon,undef);
|
|
|
|
$table->attach($search,4,5,$rows{'fpga_board_part'},$rows{'fpga_board_part'}+1,'fill','shrink',2,2);
|
|
$table->attach($search_board,4,5,$rows{'fpga_part'},$rows{'fpga_part'}+1,'fill','shrink',2,2);
|
|
$table->attach($search_dev,4,5,$rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+1,'fill','shrink',2,2);
|
|
$table->attach($search_chain,4,5,$rows{'fpga_board_order'},$rows{'fpga_board_order'}+1,'fill','shrink',2,2);
|
|
|
|
|
|
$search->signal_connect("clicked" => sub{
|
|
my $load= show_gif("icons/load.gif");
|
|
$table->attach ($load,5, 6, $rows{'fpga_board_part'},$rows{'fpga_board_part'}+ 1,'shrink','shrink',0,0);
|
|
$table->show_all;
|
|
my $result= set_xilinx_board_from_repo($self,$tview);
|
|
update_combo_entry_content($widgets{'fpga_board_part'}, $result);
|
|
$load->destroy;
|
|
$table->show_all;
|
|
});
|
|
|
|
|
|
$search_board->signal_connect("clicked" => sub{
|
|
my $load= show_gif("icons/load.gif");
|
|
$table->attach ($load,5, 6, $rows{'fpga_part'},$rows{'fpga_part'}+1, 'shrink','shrink',0,0);
|
|
$table->show_all;
|
|
my $result= get_xilinx_board_part($self,$tview);
|
|
$widgets{'fpga_part'}->set_text($result);
|
|
#print "result = $result\n";
|
|
$load->destroy;
|
|
$table->show_all;
|
|
});
|
|
$search_dev->signal_connect("clicked" => sub{
|
|
my $load= show_gif("icons/load.gif");
|
|
$table->attach ($load,5, 6, $rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+ 1,'shrink','shrink',0,0);
|
|
$table->show_all;
|
|
my $result= get_xilinx_device_names($self,$tview);
|
|
update_combo_entry_content($widgets{'fpga_hw_device'}, $result);
|
|
$load->destroy;
|
|
$table->show_all;
|
|
});
|
|
$search_chain->signal_connect("clicked" => sub{
|
|
my $targets = show_all_xilinx_targets($self,$tview);
|
|
if(!defined $targets){
|
|
add_info($tview,"Unable to find the FPGA board target list. Make sure you have connected your FPGA board to your PC first and it is powered on.\n");
|
|
return;
|
|
}
|
|
|
|
my @lines=split(/\r?\n/,$targets);
|
|
my @list1;
|
|
my @list2;
|
|
foreach my $p (@lines){
|
|
$p =~ s/^\s+//;#left trim
|
|
my @words=split(/\s+/,$p);
|
|
push (@list1,$words[0]);
|
|
push (@list2,$words[1]);
|
|
}
|
|
my $hw = $self->object_get_attribute('compile','fpga_hw_device');
|
|
if( !defined $hw){
|
|
add_colored_info($tview,"Please define the FPGA hardware device name first!\n",'red');
|
|
return;
|
|
}
|
|
my $pos = find_the_most_similar_position ($hw ,@list2);
|
|
add_info($tview,"$hw matched with target $list1[$pos] $list2[$pos] ");
|
|
$widgets{'fpga_board_order'}->set_value($list1[$pos]);
|
|
});
|
|
|
|
return ($row, $col, $table);
|
|
}
|
|
|
|
|
|
|
|
sub set_xilinx_board_from_repo{
|
|
my ($self,$tview)=@_;
|
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
|
my $result;
|
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
|
my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_boards.tcl -tclargs $repo";
|
|
my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl";
|
|
|
|
add_info($tview,"$command\n");
|
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
|
return if (!defined $stdout);
|
|
add_info($tview,"$stdout\n");
|
|
my @boards=split(/\s+/,$stdout);
|
|
my $r=0;
|
|
foreach my $board (@boards){
|
|
my @pp=split(':',$board);
|
|
if(scalar @pp == 4 && $pp[1] =~ /[a-zA-Z]+/) {
|
|
$r=1;
|
|
$result= (!defined $result)? "$board" : $result.",$board";
|
|
}
|
|
}
|
|
add_colored_info($tview,"$stdout\n",'red') if($r==0);
|
|
return $result;
|
|
}
|
|
|
|
|
|
sub get_xilinx_device_names{
|
|
my ($self,$tview)=@_;
|
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
|
my $result;
|
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
|
my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_hw_device.tcl -tclargs";
|
|
my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl";
|
|
|
|
add_info($tview,"$command\n");
|
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
|
if (!defined $stdout){
|
|
add_info($tview,"Unable to find the FPGA board devices list. Make sure you have connected your FPGA board to your PC first and it is powered on.\n");
|
|
return;
|
|
}
|
|
add_info($tview,"$stdout\n");
|
|
my $devices = capture_string_between ('\n\*RESULT:',$stdout,"\n");
|
|
my @D=split(/\s+/,$devices);
|
|
return join ',', @D;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub get_xilinx_board_part{
|
|
my ($self,$tview)=@_;
|
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
|
my $result;
|
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
|
my $board_part= $self->object_get_attribute('compile' ,'fpga_board_part');
|
|
if (!defined $board_part ){
|
|
add_colored_info($tview,"Please define the FPGA board part name first!\n",'red');
|
|
return;
|
|
}
|
|
|
|
my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_part.tcl -tclargs $board_part $repo ";
|
|
|
|
|
|
my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl";
|
|
|
|
add_info($tview,"$command\n");
|
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
|
return if (!defined $stdout);
|
|
add_info($tview,"$stdout\n");
|
|
return capture_string_between ('\n\*RESULT:',$stdout,"\n");
|
|
}
|
|
|
|
|
|
|
|
sub add_new_altera_fpga_board_widgets{
|
|
my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
|
|
my $help1="FPGA Board name. Do not use any space in given name";
|
my $help1="FPGA Board name. Do not use any space in given name";
|
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).";
|
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).";
|
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).";
|
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).";
|
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/
|
my $help4="FPGA Board USB-Blaster product ID (PID). Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find PID. Optionally you can run mpsoc/
|
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)";
|
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)";
|
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.
|
my $help5="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your hardware name. Optionally you can run \$QUARTUS_BIN/jtagconfig to find your programming hardware name.
|
an example of output from the 'jtagconfig' command:
|
an example of output from the 'jtagconfig' command:
|
\t 1) ByteBlasterMV on LPT1
|
\t 1) ByteBlasterMV on LPT1
|
\t 090010DD EPXA10
|
\t 090010DD EPXA10
|
\t 049220DD EPXA_ARM922
|
\t 049220DD EPXA_ARM922
|
or
|
or
|
\t 1) DE-SoC [1-3]
|
\t 1) DE-SoC [1-3]
|
\t 48A00477 SOCVHP5
|
\t 48A00477 SOCVHP5
|
\t 02D020DC 5CS(EBA6ES|XFC6c6ES)
|
\t 02D020DC 5CS(EBA6ES|XFC6c6ES)
|
ByteBlasterMV \& DE-SoC are the programming hardware name.";
|
ByteBlasterMV \& DE-SoC are the programming hardware name.";
|
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.";
|
my $help6="Power on your FPGA board and connect it to your PC. Then press Auto-fill button to find your device location in jtag chain. Optionally you can run \$QUARTUS_BIN/jtagconfig to find your target device location in jtag chain.";
|
|
|
|
|
|
|
|
|
my @info = (
|
my @info = (
|
{ label=>"FPGA Borad name:", param_name=>'quartus_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef},
|
{ label=>"FPGA Board Name:", param_name=>'fpga_board', type=>"Entry", default_val=>undef, content=>undef, info=>$help1, param_parent=>'compile', ref_delay=> undef},
|
{ 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},
|
{ label=>'FPGA Board Golden top QSF file:', param_name=>'board_confg_file', type=>"FILE_path", default_val=>undef, content=>"qsf", info=>$help2, param_parent=>'compile', ref_delay=>undef},
|
{ 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 },
|
{ label=>"FPGA Board Golden top Verilog file", param_name=>'fpga_board_v', type=>"FILE_path", default_val=>undef, content=>"v", info=>$help3, param_parent=>'compile',ref_delay=>undef },
|
);
|
);
|
|
|
my @usb = (
|
my @usb = (
|
{ 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},
|
{ label=>"FPGA Board USB Blaster PID:", param_name=>'quartus_pid', type=>"Entry", default_val=>undef, content=>undef, info=>$help4, param_parent=>'compile', ref_delay=> undef},
|
{ 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},
|
{ label=>"FPGA Board Programming Hardware Name:", param_name=>'quartus_hardware', type=>"Entry", default_val=>undef, content=>undef, info=>$help5, param_parent=>'compile', ref_delay=> undef},
|
{ 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},
|
{ label=>"FPGA Board 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},
|
);
|
);
|
|
|
|
|
my $col=0;
|
my $col=0;
|
my $row=0;
|
my $row=0;
|
foreach my $d (@info) {
|
foreach my $d (@info) {
|
($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");
|
($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");
|
}
|
}
|
|
|
my $labl=def_pack_vbox(FALSE, 0,(Gtk2::HSeparator->new,gen_label_in_center("FPGA Board JTAG Configuration"),Gtk2::HSeparator->new));
|
my $labl=def_pack_vbox(FALSE, 0,(gen_Hsep(),gen_label_in_center("FPGA Board JTAG Configuration"),gen_Hsep()));
|
|
|
$table->attach( $labl,0,3,$row,$row+1,'fill','shrink',2,2); $row++; $col=0;
|
$table->attach( $labl,0,3,$row,$row+1,'fill','shrink',2,2); $row++; $col=0;
|
|
|
foreach my $d (@usb) {
|
foreach my $d (@usb) {
|
($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");
|
($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");
|
Line 598... |
Line 851... |
|
|
return ($row, $col, $table);
|
return ($row, $col, $table);
|
}
|
}
|
|
|
|
|
|
sub add_new_xilinx_fpga_board_files{
|
|
my ($self,$vendor)=@_;
|
|
#check the board name
|
|
my $board_name=$self->object_get_attribute('compile','fpga_board');
|
|
return "Please define the Board Name\n" if(! defined $board_name );
|
|
return "Please define the Board Name\n" if(length($board_name) ==0 );
|
|
my $r=check_verilog_identifier_syntax($board_name);
|
|
return "Error in given Board Name: $r\n" if(defined $r );
|
|
|
|
#check xdc file
|
|
my $xdc=$self->object_get_attribute('compile','board_confg_file');
|
|
return "Please define the xdc file\n" if(!defined $xdc );
|
|
$xdc=add_project_dir_to_addr($xdc);
|
|
|
|
#check v file
|
|
my $top=$self->object_get_attribute('compile','fpga_board_v');
|
|
return "Please define the verilog file file\n" if(!defined $top );
|
|
$top=add_project_dir_to_addr($top);
|
|
|
|
#check board part
|
|
my $part=$self->object_get_attribute('compile','fpga_part');
|
|
my $board_part=$self->object_get_attribute('compile','fpga_board_part');
|
|
return "Please define at least one of FPGA board part or FPGA part names"if(!defined $part && !defined $board_part );
|
|
|
|
#make board directory
|
|
my $project_dir = get_project_dir();
|
|
my $path="$project_dir/mpsoc/boards/$vendor/$board_name";
|
|
mkpath($path,1,01777);
|
|
return "Error cannot make $path path" if ((-d $path)==0);
|
|
copy( $xdc,"$path/$board_name.xdc");
|
|
copy($top,"$path/$board_name.v");
|
|
|
sub add_new_fpga_board_files{
|
|
my $self=shift;
|
|
|
my $a=$self->object_get_attribute('compile','fpga_board_order');
|
|
my $jtag_intfc="#!/bin/bash
|
|
JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_xilinx_xsct -a $a -b 36\"
|
|
#it works only for 32-bit jtag data width for 64 pass -b 68
|
|
";
|
|
save_file ("$path/jtag_intfc.sh",$jtag_intfc);
|
|
|
|
|
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
|
my $hw_dev=$self->object_get_attribute('compile',"fpga_hw_device");
|
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
|
|
|
|
|
my $tcl="proc set_project_properties { } {\n";
|
|
if(-d $repo){
|
|
$tcl=$tcl."\tset_property \"board_part_repo_paths\" [list \"$repo\"] [current_project]\n";
|
|
}else {
|
|
$tcl=$tcl."\tset_property \"board_part_repo_paths\" [get_property LOCAL_ROOT_DIR [xhub::get_xstores xilinx_board_store]] [current_project]\n" if(defined $board_part);
|
|
}
|
|
$tcl=$tcl."\tset_property \"part\" \"$part\" [current_project]\n" if(defined $part);
|
|
$tcl=$tcl."\tset_property \"board_part\" \"$board_part\" [current_project]\n" if(defined $board_part);
|
|
$tcl=$tcl."\tset_property \"default_lib\" \"xil_defaultlib\" [current_project]\n}\n";
|
|
|
|
|
|
|
|
if (defined $hw_dev){
|
|
$tcl=$tcl."\n
|
|
proc program_board {bit_file} {
|
|
open_hw
|
|
connect_hw_server
|
|
open_hw_target
|
|
set_property PROGRAM.FILE \$bit_file [get_hw_devices $hw_dev]
|
|
program_hw_devices [get_hw_devices $hw_dev]
|
|
refresh_hw_device [get_hw_devices $hw_dev]
|
|
}
|
|
";
|
|
}
|
|
save_file ("$path/board_property.tcl",$tcl);
|
|
|
|
|
|
$self->object_add_attribute('compile','board',$board_name);
|
|
return undef;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub add_new_altera_fpga_board_files{
|
|
my ($self,$vendor)=@_;
|
|
|
#check the board name
|
#check the board name
|
my $board_name=$self->object_get_attribute('compile','quartus_board');
|
my $board_name=$self->object_get_attribute('compile','fpga_board');
|
return "Please define the Board Name\n" if(! defined $board_name );
|
return "Please define the Board Name\n" if(! defined $board_name );
|
return "Please define the Board Name\n" if(length($board_name) ==0 );
|
return "Please define the Board Name\n" if(length($board_name) ==0 );
|
my $r=check_verilog_identifier_syntax($board_name);
|
my $r=check_verilog_identifier_syntax($board_name);
|
return "Error in given Board Name: $r\n" if(defined $r );
|
return "Error in given Board Name: $r\n" if(defined $r );
|
|
|
#check qsf file
|
#check qsf file
|
my $qsf=$self->object_get_attribute('compile','quartus_qsf');
|
my $qsf=$self->object_get_attribute('compile','board_confg_file');
|
return "Please define the QSF file\n" if(!defined $qsf );
|
return "Please define the QSF file\n" if(!defined $qsf );
|
|
|
#check v file
|
#check v file
|
my $top=$self->object_get_attribute('compile','quartus_v');
|
my $top=$self->object_get_attribute('compile','fpga_board_v');
|
return "Please define the verilog file file\n" if(!defined $top );
|
return "Please define the verilog file file\n" if(!defined $top );
|
|
|
#check PID
|
#check PID
|
my $pid=$self->object_get_attribute('compile','quartus_pid');
|
my $pid=$self->object_get_attribute('compile','quartus_pid');
|
return "Please define the PID\n" if(! defined $pid );
|
return "Please define the PID\n" if(! defined $pid );
|
Line 637... |
Line 968... |
return "Please define targeted Device location in JTAG chain. The device location must be larger than zero.\n" if( $dw == 0 );
|
return "Please define targeted Device location in JTAG chain. The device location must be larger than zero.\n" if( $dw == 0 );
|
|
|
|
|
|
|
#make board directory
|
#make board directory
|
my $dir = Cwd::getcwd();
|
my $project_dir = get_project_dir();
|
my $path="$dir/../boards/$board_name";
|
my $path="$project_dir/mpsoc/boards/$vendor/$board_name";
|
mkpath($path,1,01777);
|
mkpath($path,1,01777);
|
return "Error cannot make $path path" if ((-d $path)==0);
|
return "Error cannot make $path path" if ((-d $path)==0);
|
|
|
#generate new qsf file
|
#generate new qsf file
|
$qsf=add_project_dir_to_addr($qsf);
|
$qsf=add_project_dir_to_addr($qsf);
|
Line 724... |
Line 1055... |
$self->object_add_attribute('compile','board',$board_name);
|
$self->object_add_attribute('compile','board',$board_name);
|
|
|
return undef;
|
return undef;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
sub get_pin_assignment{
|
sub get_pin_assignment{
|
my ($self,$name,$top,$target_dir,$end_func)=@_;
|
my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
my $window = def_popwin_size(80,80,"Step 2: Pin Assignment",'percent');
|
my $window = def_popwin_size(80,80,"Step 2: Pin Assignment",'percent');
|
|
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
my $scrolled_win = new Gtk2::ScrolledWindow (undef, undef);
|
my $scrolled_win = add_widget_to_scrolled_win($table);
|
$scrolled_win->set_policy( "automatic", "automatic" );
|
|
$scrolled_win->add_with_viewport($table);
|
|
|
|
|
|
my $mtable = def_table(10, 10, FALSE);
|
my $mtable = def_table(10, 10, FALSE);
|
|
|
my $next=def_image_button('icons/right.png','Next');
|
my $next=def_image_button('icons/right.png','Next');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $back=def_image_button('icons/left.png','Previous');
|
|
|
|
|
$mtable->attach_defaults($scrolled_win,0,10,0,9);
|
$mtable->attach_defaults($scrolled_win,0,10,0,9);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
|
|
my $board_name=$self->object_get_attribute('compile','board');
|
my $board_name=$self->object_get_attribute('compile','board');
|
|
|
#copy board jtag_intfc.sh file
|
#copy board jtag_intfc.sh file
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
copy("../boards/$board_name/jtag_intfc.sh","${fpath}../sw/jtag_intfc.sh");
|
copy("../boards/$vendor/$board_name/jtag_intfc.sh","${fpath}../sw/jtag_intfc.sh");
|
my $m= $self->object_get_attribute('mpsoc_name',undef);
|
my $m= $self->object_get_attribute('mpsoc_name',undef);
|
if(defined $m){ # we are compiling a complete NoC-based mpsoc
|
if(defined $m){ # we are compiling a complete NoC-based mpsoc
|
my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self);
|
my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self);
|
for (my $tile_num=0;$tile_num<$ne;$tile_num++){
|
for (my $tile_num=0;$tile_num<$ne;$tile_num++){
|
#print "$tile_num\n";
|
#print "$tile_num\n";
|
my ($soc_name,$num)= $self->mpsoc_get_tile_soc_name($tile_num);
|
my ($soc_name,$num)= $self->mpsoc_get_tile_soc_name($tile_num);
|
next if(!defined $soc_name);
|
next if(!defined $soc_name);
|
copy("../boards/$board_name/jtag_intfc.sh","${fpath}../sw/tile$tile_num/jtag_intfc.sh");
|
copy("../boards/$vendor/$board_name/jtag_intfc.sh","${fpath}../sw/tile$tile_num/jtag_intfc.sh");
|
}
|
}
|
|
|
}
|
}
|
|
|
|
|
|
|
#copy board program_device.sh file
|
#copy board program_device.sh file
|
copy("../boards/$board_name/program_device.sh","${fpath}../program_device.sh");
|
copy("../boards/$vendor/$board_name/program_device.sh","${fpath}../program_device.sh");
|
|
|
#get boards pin list
|
#get boards pin list
|
my $top_v= "../boards/$board_name/$board_name.v";
|
my $top_v= "../boards/$vendor/$board_name/$board_name.v";
|
|
|
if(!-f $top_v){
|
if(!-f $top_v){
|
message_dialog("Error: Could not load the board pin list. The $top_v does not exist!");
|
message_dialog("Error: Could not load the board pin list. The $top_v does not exist!",'error');
|
$window->destroy;
|
$window->destroy;
|
}
|
}
|
|
|
my $board=read_top_v_file($top_v);
|
my $board=read_top_v_file($top_v);
|
|
|
Line 790... |
Line 1120... |
|
|
}
|
}
|
|
|
my $row=0;
|
my $row=0;
|
my $col=0;
|
my $col=0;
|
my @lables= ('Port Direction','Port Range ','Port name ','Assigment Type','Board Port name ','Board Port Range');
|
my @labels= ('Port Direction','Port Range ','Port name ','Assignment Type','Board Port name ','Board Port Range');
|
foreach my $p (@lables){
|
foreach my $p (@labels){
|
my $l=gen_label_in_left($p);
|
my $l=gen_label_in_left($p);
|
$l->set_markup("<b> $p </b>");
|
$l->set_markup("<b> $p </b>");
|
$table->attach ($l, $col,$col+1, $row, $row+1,'fill','shrink',2,2);
|
$table->attach ($l, $col,$col+1, $row, $row+1,'fill','shrink',2,2);
|
$col++
|
$col++
|
}
|
}
|
Line 822... |
Line 1152... |
chomp $value;
|
chomp $value;
|
($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l});
|
($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l});
|
# print"($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l})\n";
|
# print"($portrange=$portrange)=~ s/\b$l\b/$value/g if(defined $param{$l})\n";
|
}
|
}
|
}
|
}
|
|
|
|
my($s1,$s2)=split (":",$portrange);
|
|
{
|
|
no warnings 'numeric';
|
|
$s1 = eval $s1;
|
|
$s2 = eval $s2;
|
|
}
|
$portrange = "[ $portrange ]" ;
|
$portrange = "[ $portrange ]" ;
|
|
if(defined $s1 && defined $s2 ){
|
|
$portrange = "" if($s1 eq 0 && $s2 eq 0); #the upper and lower range are equal zero so remove it
|
|
}
|
}
|
}
|
|
|
my $label1= gen_label_in_left(" $porttype");
|
my $label1= gen_label_in_left(" $porttype");
|
my $label2= gen_label_in_left(" $portrange");
|
my $label2= gen_label_in_left(" $portrange");
|
my $label3= gen_label_in_left(" $p");
|
my $label3= gen_label_in_left(" $p");
|
Line 848... |
Line 1188... |
my $saved=$self->object_get_attribute('compile_pin_pos',$p);
|
my $saved=$self->object_get_attribute('compile_pin_pos',$p);
|
my $box;
|
my $box;
|
my $loc=$row;
|
my $loc=$row;
|
if(defined $saved) {
|
if(defined $saved) {
|
my @indices=@{$saved};
|
my @indices=@{$saved};
|
my $path = Gtk2::TreePath->new_from_indices(@indices);
|
my $path = TreePath_new_from_indices(@indices);
|
my $iter = $models{$type}->get_iter($path);
|
my $iter = $models{$type}->get_iter($path);
|
undef $path;
|
undef $path;
|
$combo->set_active_iter($iter);
|
$combo->set_active_iter($iter);
|
$box->destroy if(defined $box);
|
$box->destroy if(defined $box);
|
my $text=$self->object_get_attribute('compile_pin',$p);
|
my $text=$self->object_get_attribute('compile_pin',$p);
|
Line 885... |
Line 1225... |
|
|
}
|
}
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
quartus_compilation($self,$board,$name,$top,$target_dir,$end_func);
|
fpga_compilation($self,$board,$name,$top,$target_dir,$end_func,$vendor);
|
|
|
});
|
});
|
$back-> signal_connect("clicked" => sub{
|
$back-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
select_compiler($self,$name,$top,$target_dir,$end_func);
|
select_compiler($self,$name,$top,$target_dir,$end_func,$vendor);
|
|
|
});
|
});
|
|
|
|
|
$window->add ($mtable);
|
$window->add ($mtable);
|
Line 904... |
Line 1244... |
|
|
|
|
|
|
|
|
|
|
sub quartus_compilation{
|
sub fpga_compilation{
|
my ($self,$board,$name,$top,$target_dir,$end_func)=@_;
|
my ($self,$board,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
|
|
my $run=def_image_button('icons/gate.png','Compile');
|
my $run=def_image_button('icons/gate.png','Compile');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $regen=def_image_button('icons/refresh.png','Regenerate Top.v');
|
my $regen=def_image_button('icons/refresh.png','Regenerate Top.v');
|
my $prog=def_image_button('icons/write.png','Program the board');
|
my $prog=def_image_button('icons/write.png','Program the board');
|
Line 928... |
Line 1268... |
$table->attach($prog,9,10,1,2,'shrink','shrink',2,2);
|
$table->attach($prog,9,10,1,2,'shrink','shrink',2,2);
|
|
|
|
|
|
|
$regen-> signal_connect("clicked" => sub{
|
$regen-> signal_connect("clicked" => sub{
|
my $dialog = Gtk2::MessageDialog->new (my $window,
|
|
'destroy-with-parent',
|
my $response = yes_no_dialog("Are you sure you want to regenerate the Top.v file? Note that any changes you have made will be lost");
|
'question', # message type
|
|
'yes-no', # which set of buttons?
|
|
"Are you sure you want to regenaret the Top.v file? Note that any changes you have made will be lost");
|
|
my $response = $dialog->run;
|
|
if ($response eq 'yes') {
|
if ($response eq 'yes') {
|
gen_top_v($self,$board,$name,$top);
|
gen_top_v($self,$board,$name,$top);
|
$app->load_source("$board_top_file");
|
$app->refresh_source("$board_top_file");
|
}
|
}
|
$dialog->destroy;
|
|
|
|
});
|
});
|
|
|
|
|
|
|
$back-> signal_connect("clicked" => sub{
|
$back-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
get_pin_assignment($self,$name,$top,$target_dir);
|
get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);
|
|
|
});
|
});
|
|
|
|
|
#compile
|
#compile
|
Line 959... |
Line 1293... |
my $load= show_gif("icons/load.gif");
|
my $load= show_gif("icons/load.gif");
|
$table->attach ($load,8, 9, 1,2,'shrink','shrink',2,2);
|
$table->attach ($load,8, 9, 1,2,'shrink','shrink',2,2);
|
$load->show_all;
|
$load->show_all;
|
|
|
set_gui_status($self,'save_project',1);
|
set_gui_status($self,'save_project',1);
|
$app->do_save();
|
$app->ask_to_save_changes();
|
my $error = 0;
|
|
add_info(\$tview,"CREATE: start creating Quartus project in $target_dir\n");
|
|
|
|
#get list of source file
|
quartus_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Altera');
|
add_info(\$tview," Read the list of all source files $target_dir/src_verilog\n");
|
xilinx_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Xilinx');
|
my @files = File::Find::Rule->file()
|
|
->name( '*.v','*.V','*.sv' )
|
|
->in( "$target_dir/src_verilog" );
|
|
|
|
#make sure source files have key word 'module'
|
$load->destroy;
|
my @sources;
|
|
foreach my $p (@files){
|
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
|
}
|
|
my $files = join ("\n",@sources);
|
|
add_info(\$tview,"$files\n");
|
|
|
|
#creat project qsf file
|
});
|
my $qsf_file="$target_dir/${name}.qsf";
|
|
save_file ($qsf_file,"# Generated using ProNoC\n");
|
|
|
|
#append global assignets to qsf file
|
|
my $board_name=$self->object_get_attribute('compile','board');
|
|
my @qsfs = glob("../boards/$board_name/*.qsf");
|
|
if(!defined $qsfs[0]){
|
|
message_dialog("Error: ../boards/$board_name folder does not contain the qsf file.!");
|
|
$window->destroy;
|
|
}
|
|
|
|
|
#Programe the board
|
|
$prog-> signal_connect("clicked" => sub{
|
|
quartus_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Altera');
|
|
vivado_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Xilinx');
|
|
});
|
|
|
|
}
|
|
|
|
sub vivado_program_the_board {
|
|
my ($self,$tview,$target_dir,$name,$vendor) =@_;
|
|
|
|
my $bit_file="$target_dir/Vivado/xilinx_compile/${name}.runs/impl_1/Top.bit";
|
|
|
|
|
|
|
|
unless (-f "$target_dir/Vivado/program_board.tcl"){
|
|
#create tcl file
|
|
my $xpr = "\$tcl_path/xilinx_compile/${name}.xpr";
|
|
my $tcl="
|
|
#Get tcl shell path relative to current script
|
|
set tcl_path [file dirname [info script]]
|
|
|
|
set projectName $name
|
|
|
|
source \"\$tcl_path/board_property.tcl\"
|
|
set projectXpr \"$xpr\"
|
|
#Open project
|
|
open_project \$projectXpr
|
|
program_board \"\$tcl_path/xilinx_compile/${name}.runs/impl_1/Top.bit\"
|
|
close_project
|
|
exit
|
|
|
|
";
|
|
save_file ("$target_dir/Vivado/program_board.tcl",$tcl);
|
|
add_info($tview,"File $target_dir/Vivado/program_board.tcl is created\n");
|
|
}
|
|
|
|
#check bit file existance
|
|
unless (-f $bit_file){
|
|
add_colored_info($tview,"Could not find $bit_file. Click on project Compile button first and make sure it runs successfully.",'red');
|
|
return
|
|
}
|
|
|
|
|
|
#run vivado using program_board.tcl
|
|
my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/program_board.tcl");
|
|
add_colored_info($tview,"Board is programmed successfully!\n",'blue') if($error==0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub quartus_program_the_board{
|
|
my ($self,$tview,$target_dir,$name,$vendor)=@_;
|
|
my $error = 0;
|
|
my $sof_file="$target_dir/Quartus/output_files/${name}.sof";
|
|
my $bash_file="$target_dir/program_device.sh";
|
|
|
|
add_info($tview,"Program the board using Quartus_pgm and $sof_file file\n");
|
|
#check if the programming file exists
|
|
unless (-f $sof_file) {
|
|
add_colored_info($tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red');
|
|
$error=1;
|
|
}
|
|
#check if the program_device.sh file exists
|
|
unless (-f $bash_file) {
|
|
add_colored_info($tview,"\tThe $bash_file does not exist! This file varies depending on your target board and must be available inside mpsoc/boards/$vendor/[board_name].\n", 'red');
|
|
$error=1;
|
|
}
|
|
return if($error);
|
|
my $command = "bash $bash_file $sof_file";
|
|
add_info($tview,"$command\n");
|
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
|
|
if(length $stderr>1){
|
|
add_colored_info($tview,"$stderr\n",'red');
|
|
add_colored_info($tview,"Board was not programmed successfully!\n",'red');
|
|
}else {
|
|
if($exit){
|
|
add_colored_info($tview,"$stdout\n",'red');
|
|
add_colored_info($tview,"Board was not programmed successfully!\n",'red');
|
|
}else{
|
|
add_info($tview,"$stdout\n");
|
|
add_colored_info($tview,"Board is programmed successfully!\n",'blue');
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
sub quartus_run_compile{
|
|
my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_;
|
|
|
|
my $error = 0;
|
|
add_info($tview,"CREATE: start creating Quartus project in $target_dir/Quartus folder\n");
|
|
|
|
mkpath("$target_dir/Quartus",1,01777);
|
|
|
|
#get list of source file
|
|
add_info($tview," Read the list of all source files $target_dir/src_verilog\n");
|
|
my @files = File::Find::Rule->file()
|
|
->name( '*.v','*.V','*.sv' )
|
|
->in( "$target_dir/src_verilog" );
|
|
|
|
#make sure source files have key word 'module'
|
|
my @sources;
|
|
foreach my $p (@files){
|
|
push (@sources,$p) if(check_file_has_string($p,'endpackage'));
|
|
}
|
|
foreach my $p (@files){
|
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
|
}
|
|
my $files = join ("\n",@sources);
|
|
add_info($tview,"$files\n");
|
|
|
|
#creat project qsf file
|
|
my $qsf_file="$target_dir/Quartus/${name}.qsf";
|
|
save_file ($qsf_file,"# Generated using ProNoC\n");
|
|
|
|
#append global assignets to qsf file
|
|
my $board_name=$self->object_get_attribute('compile','board');
|
|
my @qsfs = glob("../boards/$vendor/$board_name/*.qsf");
|
|
if(!defined $qsfs[0]){
|
|
message_dialog("Error: ../boards/$vendor/$board_name folder does not contain the qsf file.!",'error');
|
|
$window->destroy;
|
|
}
|
|
|
my $assignment_file = $qsfs[0];
|
my $assignment_file = $qsfs[0];
|
|
|
if(-f $assignment_file){
|
if(-f $assignment_file){
|
merg_files ($assignment_file,$qsf_file);
|
merg_files ($assignment_file,$qsf_file);
|
}
|
}
|
|
|
|
my %paths;
|
|
|
#add the list of source fils to qsf file
|
#add the list of source fils to qsf file
|
my $s="\n\n\n set_global_assignment -name TOP_LEVEL_ENTITY Top\n";
|
my $s="\n\n\n set_global_assignment -name TOP_LEVEL_ENTITY Top\n";
|
foreach my $p (@sources){
|
foreach my $p (@sources){
|
my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
|
my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
|
$s="$s set_global_assignment -name VERILOG_FILE $p\n" if ($suffix eq ".v");
|
$s="$s set_global_assignment -name VERILOG_FILE $p\n" if ($suffix eq ".v");
|
$s="$s set_global_assignment -name SYSTEMVERILOG_FILE $p\n" if ($suffix eq ".sv");
|
$s="$s set_global_assignment -name SYSTEMVERILOG_FILE $p\n" if ($suffix eq ".sv");
|
|
$paths{$path}=1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach my $p (sort keys %paths){
|
|
$s="$s set_global_assignment -name SEARCH_PATH $p\n";
|
}
|
}
|
|
|
append_text_to_file($qsf_file,$s);
|
append_text_to_file($qsf_file,$s);
|
add_info(\$tview,"\n Qsf file has been created\n");
|
add_info($tview,"\n Qsf file has been created\n");
|
|
|
|
|
|
|
|
|
#start compilation
|
#start compilation
|
my $Quartus_bin= $self->object_get_attribute('compile','quartus_bin');;
|
my $Quartus_bin= $self->object_get_attribute('compile','quartus bin');
|
add_info(\$tview, "Start Quartus compilation.....\n");
|
my @qfiles = ("quartus_map","quartus_fit","quartus_asm","quartus_sta");
|
|
foreach my $f (@qfiles){
|
|
unless(-f "$Quartus_bin/$f" ){
|
|
$error=1;
|
|
add_colored_info($tview, "$Quartus_bin/$f No such file or directory\n",'red');
|
|
last;
|
|
}
|
|
|
|
}
|
|
|
|
my $run_sh = "#!/bin/bash
|
|
$Quartus_bin/quartus_map --64bit $name --read_settings_files=on
|
|
$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on
|
|
$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on
|
|
$Quartus_bin/quartus_sta --64bit $name
|
|
";
|
|
|
|
save_file("$target_dir/Quartus/run.sh", $run_sh);
|
|
|
|
add_info($tview, "Start Quartus compilation.....\n");
|
my @compilation_command =(
|
my @compilation_command =(
|
"cd \"$target_dir/\" \n xterm -e bash -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status' ",
|
"cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ",
|
"cd \"$target_dir/\" \n xterm -e bash -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status' ",
|
"cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ",
|
"cd \"$target_dir/\" \n xterm -e bash -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status' ",
|
"cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ",
|
"cd \"$target_dir/\" \n xterm -e bash -c '$Quartus_bin/quartus_sta --64bit $name;echo \$? > status' ");
|
"cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_sta --64bit $name; echo \$? > status; sleep 1 ' ");
|
|
|
foreach my $cmd (@compilation_command){
|
foreach my $cmd (@compilation_command){
|
add_info(\$tview,"$cmd\n");
|
last if($error);
|
unlink "$target_dir/status";
|
add_info($tview,"$cmd\n");
|
my ($stdout,$exit)=run_cmd_in_back_ground_get_stdout( $cmd);
|
unlink "$target_dir/Quartus/status";
|
open(my $fh, "<$target_dir/status") || die "Can not open: $!";
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd);
|
|
if($exit){
|
|
add_colored_info($tview, "$stdout\n",'red') if(defined $stdout);
|
|
add_colored_info($tview, "$stderr\n",'red') if(defined $stderr);
|
|
$error=1;
|
|
last;
|
|
}
|
|
|
|
open(my $fh, "<$target_dir/Quartus/status") || die "Can not open: $!";
|
read($fh,my $status,1);
|
read($fh,my $status,1);
|
close($fh);
|
close($fh);
|
if("$status" != "0"){
|
if("$status" != "0"){
|
($stdout,$exit)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/output_files/\" \n grep -h \"Error (\" *");
|
($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/Quartus/output_files/\" \n grep -h \"Error (\" *");
|
add_colored_info(\$tview,"$stdout\n Quartus compilation failed !\n",'red');
|
add_colored_info($tview,"$stderr\n",'red') if(defined $stderr);
|
|
add_colored_info($tview,"$stdout\n",'red');
|
$error=1;
|
$error=1;
|
last;
|
last;
|
}
|
}
|
}
|
}
|
add_colored_info(\$tview,"Quartus compilation is done successfully in $target_dir!\n", 'blue') if($error==0);
|
add_colored_info($tview,"Quartus compilation failed !\n",'red') if($error==1);
|
|
add_colored_info($tview,"Quartus compilation is done successfully in $target_dir/Quartus!\n", 'blue') if($error==0);
|
if (defined $end_func){
|
if (defined $end_func){
|
if ($error==0){
|
if ($error==0){
|
$end_func->($self);
|
$end_func->($self);
|
$window->destroy;
|
$window->destroy;
|
}else {
|
}else {
|
message_dialog("Error in Quartus compilation!",'error');
|
message_dialog("Error in Quartus compilation!",'error');
|
}
|
}
|
}
|
}
|
$load->destroy;
|
|
|
|
});
|
|
|
|
|
|
#Programe the board
|
}
|
$prog-> signal_connect("clicked" => sub{
|
|
my $error = 0;
|
|
my $sof_file="$target_dir/output_files/${name}.sof";
|
|
my $bash_file="$target_dir/program_device.sh";
|
|
|
|
add_info(\$tview,"Programe the board using quartus_pgm and $sof_file file\n");
|
|
#check if the programming file exists
|
|
unless (-f $sof_file) {
|
|
add_colored_info(\$tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red');
|
|
$error=1;
|
|
|
sub xilinx_run_compile{
|
|
my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_;
|
|
|
|
add_info($tview,"CREATE: start creating Vivado project in $target_dir/Vivado\n");
|
|
#get list of source file
|
|
add_info($tview," Read the list of all source files $target_dir/src_verilog\n");
|
|
my @files = File::Find::Rule->file()
|
|
->name( '*.v','*.V','*.sv' )
|
|
->in( "$target_dir/src_verilog" );
|
|
|
|
#make sure source files have key word 'module'
|
|
my @sources;
|
|
foreach my $p (@files){
|
|
push (@sources,$p) if(check_file_has_string($p,'endpackage'));
|
}
|
}
|
#check if the program_device.sh file exists
|
foreach my $p (@files){
|
unless (-f $bash_file) {
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
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');
|
|
$error=1;
|
|
}
|
}
|
return if($error);
|
|
my $command = "bash $bash_file $sof_file";
|
my %paths;
|
add_info(\$tview,"$command\n");
|
foreach my $p (@files){
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($command);
|
my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
|
if(length $stderr>1){
|
#print "$path\n";
|
add_colored_info(\$tview,"$stderr\n",'red');
|
my $remove="$target_dir/";
|
add_colored_info(\$tview,"Board was not programed successfully!\n",'red');
|
$path =~ s/$remove//;
|
|
$paths{$path}=1;
|
|
}
|
|
|
|
|
|
|
|
|
|
my $incdir="set include_dir_list [list";
|
|
foreach my $p (sort keys %paths){
|
|
$incdir.=" \$Dir/$p";
|
|
}
|
|
$incdir.="]";
|
|
|
|
my $files = join ("\n",@sources);
|
|
|
|
|
|
|
|
#add mem initial file to sources
|
|
my $mem_files="";
|
|
my @initial_files = File::Find::Rule->file()
|
|
->name( '*.mem')
|
|
->in( "$target_dir/sw" );
|
|
mkpath("$target_dir/Vivado/xilinx_mem",1,01777) unless -f "$target_dir/Vivado/xilinx_mem";
|
|
foreach my $f (@initial_files){
|
|
# /home/alireza/work/hca_git/mpsoc_work/SOC/mor1k_soc/sw/RAM/ram0.mif fpr soc
|
|
# /home/alireza/work/hca_git/mpsoc_work/MPSOC/newAdder/sw/tile0/RAM/ram0.mif fpr mpsoc
|
|
my @m = split('\/sw\/',$f );
|
|
my $d = $m[-1];#take the last file path name after /sw/
|
|
$d=~ s/RAM//g; #remove RAM
|
|
$d=~ s/\///g; #remove /
|
|
$d = "tile0".$d unless($m[-1]=~/^tile/); #add tile0 to soc
|
|
copy($f,"$target_dir/Vivado/xilinx_mem/$d");
|
|
$mem_files="$mem_files \$tcl_path/xilinx_mem/$d";
|
|
}
|
|
add_info($tview,"HDL sources:\n$files\nMem sources:\n$mem_files\n");
|
|
#make tcl file
|
|
my $tcl="
|
|
#Get tcl shell path relative to current script
|
|
set tcl_path [file dirname [info script]]
|
|
set Dir \"\$tcl_path/..\"
|
|
";
|
|
|
|
$tcl=$tcl."set projectName $name";
|
|
|
|
$tcl =$tcl."
|
|
source \"\$tcl_path/board_property.tcl\"
|
|
#Create output directory and clear contents
|
|
set outputdir \"\$tcl_path/xilinx_compile\"";
|
|
$tcl =$tcl.'
|
|
file mkdir $outputdir
|
|
set files [glob -nocomplain "$outputdir/*"]
|
|
if {[llength $files] != 0} {
|
|
puts "deleting contents of $outputdir"
|
|
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents
|
|
} else {
|
|
puts "$outputdir is empty"
|
|
}
|
|
|
|
#Create project
|
|
create_project $projectName $outputdir
|
|
|
|
set_project_properties
|
|
|
|
#add source files to Vivado project
|
|
';
|
|
|
|
#get top level port names
|
|
#get boards pin list
|
|
my $top_v= "$target_dir/src_verilog/Top.v";
|
|
if(!-f $top_v){
|
|
message_dialog("Error: Could not load the board pin list. The Top.v does not exist!",'error');
|
|
$window->destroy;
|
|
}
|
|
|
|
|
|
my @ports=verilog_file_get_ports_list(read_verilog_file($top_v),"Top");
|
|
|
|
#get board tcl
|
|
my $board_name=$self->object_get_attribute('compile','board');
|
|
my @tcls= glob("../boards/$vendor/$board_name/*.tcl");
|
|
foreach my $f (@tcls){
|
|
copy($f,"$target_dir/Vivado");
|
|
}
|
|
|
|
#get board xdc
|
|
my @xdcs= glob("../boards/$vendor/$board_name/*.xdc");
|
|
my $i=1;
|
|
|
|
foreach my $f (@xdcs){
|
|
my $out="";
|
|
#capture file content
|
|
my $string= load_file($f);
|
|
my @lines=split('\n',$string);
|
|
#make sure lines describing the port name are not comment
|
|
foreach my $l (@lines){
|
|
foreach my $p (@ports){
|
|
|
|
$l=~ s/^\s*#/ /g if($l =~ /^\s*#/ && $l =~ /\[\s*get_ports\s*[{\s]\s*$p[\s\[\]\}]/ );# /\[get_ports\s*{\s*$p[\s\}\[]/);
|
|
|
|
}
|
|
$out=$out."$l\n";
|
|
}
|
|
my ($fname,$fpath,$fsuffix) = fileparse("$f",qr"\..[^.]*$");
|
|
my $xdc_file = "$target_dir/Vivado/$fname.xdc";
|
|
#save new xdc file
|
|
save_file($xdc_file,$out);
|
|
#add xdc to tcl file
|
|
$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/$fname.xdc\n";
|
|
$i++;
|
|
}
|
|
|
|
#internal clock constrain
|
|
my $clk_xdc=get_clk_constrain_file($self);
|
|
#save_file ("$target_dir/clk.xdc",$clk_xdc);
|
|
#$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/clk.xdc\n";
|
|
|
|
|
|
|
|
$tcl =$tcl."add_files ";
|
|
#add hdl sources
|
|
foreach my $f (@sources){
|
|
my $p =cut_dir_path($f,'src_verilog');
|
|
$tcl =$tcl." \$Dir/src_verilog/$p ";
|
|
}
|
|
$tcl =$tcl."\n";
|
|
|
|
$tcl =$tcl."#add memory initial files to Vivado project
|
|
add_files -norecurse $mem_files" if(length($mem_files)>3);
|
|
|
|
|
|
$tcl =$tcl."\n set_property \"top\" \"Top\" [current_fileset]\n";
|
|
$tcl =$tcl."
|
|
update_compile_order -fileset sources_1
|
|
#launch synthesis
|
|
|
|
# Make all reset syncron
|
|
set_property verilog_define {{SYNC_RESET_MODE}} [current_fileset]
|
|
|
|
# include source dirs
|
|
$incdir
|
|
set_property include_dirs \$include_dir_list [current_fileset]
|
|
|
|
launch_runs synth_1
|
|
wait_on_run synth_1
|
|
#Run implementation and generate bitstream
|
|
set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1]
|
|
launch_runs impl_1 -to_step write_bitstream
|
|
wait_on_run impl_1
|
|
puts \"Implementation done!\"
|
|
";
|
|
|
|
|
|
$tcl =$tcl."\nexit";
|
|
#creat make_project tcl file
|
|
save_file ("$target_dir/Vivado/make_project.tcl",$tcl);
|
|
|
|
my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/make_project.tcl");
|
|
add_colored_info($tview,"Vivado compilation is done successfully in $target_dir/Vivado!\n", 'blue') if($error==0);
|
|
if (defined $end_func){
|
|
if ($error==0){
|
|
$end_func->($self);
|
|
$window->destroy;
|
}else {
|
}else {
|
|
message_dialog("Error in Vivado compilation!",'error');
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
sub run_vivado {
|
|
my ($self,$target_dir,$tview,$tcl)=@_;
|
|
my $error=0;
|
|
#start compilation
|
|
my $vivado_bin= $self->object_get_attribute('compile','vivado bin');
|
|
add_info($tview, "Start compilation using vivado.....\n");
|
|
my @compilation_command =(
|
|
"cd \"$target_dir/Vivado/\" \n xterm -e bash -c '$vivado_bin/vivado -mode tcl -source $tcl'"
|
|
);
|
|
|
|
save_file("$target_dir/Vivado/run.sh", "#!/bin/bash \n $vivado_bin/vivado -mode tcl -source $tcl");
|
|
|
|
|
|
my $log="$target_dir/Vivado/vivado.log";
|
|
#unlink $log;
|
|
|
|
foreach my $cmd (@compilation_command){
|
|
add_info($tview,"$cmd\n");
|
|
|
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd);
|
if($exit){
|
if($exit){
|
add_colored_info(\$tview,"$stdout\n",'red');
|
$error=1;
|
add_colored_info(\$tview,"Board was not programed successfully!\n",'red');
|
add_colored_info($tview, "$stdout\n",'red') if(defined $stdout);
|
}else{
|
add_colored_info($tview, "$stderr\n",'red') if(defined $stderr);
|
add_info(\$tview,"$stdout\n");
|
}
|
add_colored_info(\$tview,"Board is programed successfully!\n",'blue');
|
|
|
|
}
|
}
|
|
|
|
#check vivado.log for error
|
|
my $r;
|
|
open my $fd, "<" , $log or $r=$!;
|
|
if(defined $r ) {
|
|
add_colored_info($tview, "could not open $log to check errors: $r\n",'red');
|
|
$error=1;
|
}
|
}
|
});
|
else{
|
|
|
|
#check error
|
|
while (my $line = <$fd>) {
|
|
chomp $line;
|
|
if( $line =~ /ERROR:/){
|
|
add_colored_info($tview, "$line\n",'red');
|
|
$error=1;
|
|
}
|
|
}
|
|
|
|
#check warning
|
|
close($fd);
|
|
open $fd, "<" , $log;
|
|
#print "$log\n";
|
|
if($error==0){
|
|
while (my $line = <$fd>) {
|
|
chomp $line;
|
|
if( $line =~ /^\s*WARNING:/){
|
|
add_info($tview, "$line\n");
|
|
|
}
|
}
|
|
}
|
|
}
|
|
|
|
#check critical warning
|
|
close($fd);
|
|
open $fd, "<" , $log;
|
|
#print "$log\n";
|
|
if($error==0){
|
|
while (my $line = <$fd>) {
|
|
chomp $line;
|
|
if( $line =~ /^\s*CRITICAL WARNING:/){
|
|
add_colored_info($tview, "$line\n",'green');
|
|
}
|
|
}
|
|
}
|
|
close($fd);
|
|
}
|
|
return $error;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
sub modelsim_compilation{
|
sub modelsim_compilation{
|
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
#my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
|
#my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
|
|
|
|
|
my $run=def_image_button('icons/run.png','run');
|
my $run=def_image_button('icons/run.png','_run',FALSE,1);
|
my $back=def_image_button('icons/left.png','Previous');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $regen=def_image_button('icons/refresh.png','Regenerate testbench.v');
|
my $regen=def_image_button('icons/refresh.png','Regenerate testbench.v');
|
|
|
|
|
|
#creat modelsim dir
|
|
|
|
my $model="$target_dir/Modelsim";
|
|
unlink("$model/model.tcl");
|
|
rmtree("$target_dir/rtl_work");
|
|
mkpath("$model/rtl_work",1,01777);
|
|
|
|
my ($app,$table,$tview,$window) = software_main("$target_dir/Modelsim",undef);
|
#create testbench.v
|
#create testbench.v
|
gen_modelsim_soc_testbench ($self,$name,$top,$target_dir) unless (-f "$target_dir/src_verilog/testbench.v");
|
gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview) unless (-f "$target_dir/Modelsim/testbench.v");
|
|
$app->refresh_source("$target_dir/Modelsim/testbench.v");
|
|
|
|
|
|
|
my ($app,$table,$tview,$window) = software_main("$target_dir/src_verilog",'testbench.v');
|
add_info($tview,"create Modelsim dir in $target_dir\n");
|
$table->attach($back,1,2,1,2,'shrink','shrink',2,2);
|
$table->attach($back,1,2,1,2,'shrink','shrink',2,2);
|
$table->attach($regen,4,5,1,2,'shrink','shrink',2,2);
|
$table->attach($regen,4,5,1,2,'shrink','shrink',2,2);
|
$table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
|
$table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
|
|
|
|
|
|
|
$regen-> signal_connect("clicked" => sub{
|
$regen-> signal_connect("clicked" => sub{
|
my $dialog = Gtk2::MessageDialog->new (my $window,
|
my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.v file? Note that any changes you have made will be lost");
|
'destroy-with-parent',
|
|
'question', # message type
|
|
'yes-no', # which set of buttons?
|
|
"Are you sure you want to regenaret the testbench.v file? Note that any changes you have made will be lost");
|
|
my $response = $dialog->run;
|
|
if ($response eq 'yes') {
|
if ($response eq 'yes') {
|
gen_modelsim_soc_testbench ($self,$name,$top,$target_dir);
|
gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview);
|
$app->load_source("$target_dir/src_verilog/testbench.v");
|
$app->refresh_source("$target_dir/Modelsim/testbench.v");
|
}
|
}
|
$dialog->destroy;
|
|
|
|
});
|
});
|
|
|
$back-> signal_connect("clicked" => sub{
|
$back-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
select_compiler($self,$name,$top,$target_dir);
|
select_compiler($self,$name,$top,$target_dir);
|
|
|
});
|
});
|
|
|
|
#Get the list of all verilog files in src_verilog folder
|
|
add_info($tview,"Get the list of all Verilog files in src_verilog folder\n");
|
|
my @files = File::Find::Rule->file()
|
|
->name( '*.v','*.V','*.sv' )
|
|
->in( "$target_dir/src_verilog" );
|
|
|
|
#get list of all verilog files in src_sim folder
|
|
my @sim_files = File::Find::Rule->file()
|
|
->name( '*.v','*.V','*.sv' )
|
|
->in( "$target_dir/src_sim" );
|
|
push (@files, @sim_files);
|
|
#add testnemch.v
|
|
push (@files, "$target_dir/Modelsim/testbench.v");
|
|
|
|
#create a file list
|
|
my $tt =create_file_list($target_dir,\@files,'modelsim');
|
|
save_file("$target_dir/Modelsim/file_list.f", "$tt");
|
|
|
#creat modelsim dir
|
|
add_info(\$tview,"creat Modelsim dir in $target_dir\n");
|
|
my $model="$target_dir/Modelsim";
|
|
rmtree("$model");
|
|
rmtree("$target_dir/rtl_work");
|
|
mkpath("$model/rtl_work",1,01777);
|
|
|
|
#create modelsim.tcl file
|
#create modelsim.tcl file
|
my $tcl="#!/usr/bin/tclsh
|
my $tcl="#!/usr/bin/tclsh
|
|
|
|
|
Line 1150... |
Line 1885... |
if {[file exists rtl_work]} {
|
if {[file exists rtl_work]} {
|
vdel -lib rtl_work -all
|
vdel -lib rtl_work -all
|
}
|
}
|
vlib rtl_work
|
vlib rtl_work
|
vmap work rtl_work
|
vmap work rtl_work
|
";
|
|
|
|
#Get the list of all verilog files in src_verilog folder
|
|
add_info(\$tview,"Get the list of all verilog files in src_verilog folder\n");
|
|
my @files = File::Find::Rule->file()
|
|
->name( '*.v','*.V','*.sv' )
|
|
->in( "$target_dir/src_verilog" );
|
|
#make sure source files have key word 'module'
|
|
my @sources;
|
|
foreach my $p (@files){
|
|
my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
|
|
if(check_file_has_string($p,'module')){
|
|
if ($suffix eq ".sv"){$tcl=$tcl."vlog -sv -work work +incdir+$path \{$p\}\n";}
|
|
else {$tcl=$tcl."vlog -vlog01compat -work work +incdir+$path \{$p\}\n";}
|
|
}
|
|
}
|
|
|
|
$tcl="$tcl
|
vlog +acc=rn -F $target_dir/Modelsim/file_list.f
|
|
|
vsim -t 1ps -L rtl_work -L work -voptargs=\"+acc\" testbench
|
vsim -t 1ps -L rtl_work -L work -voptargs=\"+acc\" testbench
|
|
|
add wave *
|
add wave *
|
view structure
|
view structure
|
view signals
|
view signals
|
run -all
|
run -all
|
";
|
";
|
add_info(\$tview,"Create run.tcl file\n");
|
add_info($tview,"Create model.tcl, run.sh files\n");
|
save_file ("$model/run.tcl",$tcl);
|
save_file ("$model/model.tcl",$tcl);
|
|
my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin');
|
|
my $cmd="cd $target_dir/Modelsim; rm -Rf rtl_work; $modelsim_bin/vsim -do $model/model.tcl";
|
|
save_file ("$model/run.sh",'#!/bin/bash'."\n".$cmd);
|
|
|
$run -> signal_connect("clicked" => sub{
|
$run -> signal_connect("clicked" => sub{
|
set_gui_status($self,'save_project',1);
|
set_gui_status($self,'save_project',1);
|
$app->do_save();
|
$app->ask_to_save_changes();
|
my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin');
|
|
my $cmd="cd $target_dir; $modelsim_bin/vsim -do $model/run.tcl";
|
|
|
|
add_info(\$tview,"$cmd\n");
|
|
|
add_info($tview,"$cmd\n");
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
if(length $stderr>1){
|
if(length $stderr>1){
|
add_colored_info(\$tview,"$stderr\n","red");
|
add_colored_info($tview,"$stderr\n","red");
|
|
|
}else {
|
}else {
|
add_info(\$tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
}
|
}
|
|
|
});
|
});
|
|
|
#$window->show_all();
|
#$window->show_all();
|
Line 1201... |
Line 1925... |
|
|
|
|
# source files : $target_dir/src_verilog
|
# source files : $target_dir/src_verilog
|
# work dir : $target_dir/src_verilog
|
# work dir : $target_dir/src_verilog
|
|
|
sub verilator_compilation {
|
|
my ($top_ref,$target_dir,$outtext)=@_;
|
|
|
|
my %tops = %{$top_ref};
|
|
#creat verilator dir
|
|
add_info(\$outtext,"creat verilator dir in $target_dir\n");
|
|
my $verilator="$target_dir/verilator";
|
|
rmtree("$verilator/rtl_work");
|
|
rmtree("$verilator/processed_rtl");
|
|
mkpath("$verilator/rtl_work/",1,01777);
|
|
mkpath("$verilator/processed_rtl/",1,01777);
|
|
|
|
my @ff = ("$target_dir/src_verilog");
|
|
push (@ff,"$target_dir/src_verilator") if (-d "$target_dir/src_verilator");
|
|
|
|
|
|
|
sub create_file_list {
|
|
my ($target_dir,$files_ref, $platform)=@_;
|
|
my @ff=@{$files_ref} if(defined $files_ref);
|
|
my $pakages="";
|
|
my $file_list="";
|
|
my $include="";
|
|
|
#copy all verilog files in rtl_work folder
|
my %paths;
|
add_info(\$outtext,"Copy all verilog files in rtl_work folder\n");
|
|
my @files = File::Find::Rule->file()
|
my @files = File::Find::Rule->file()
|
->name( '*.v','*.V','*.sv','*.vh')
|
->name( '*.v','*.V','*.sv','*.vh')
|
->in( @ff );
|
->in( @ff );
|
|
|
|
@ff =uniq( @ff);
|
|
|
foreach my $file (@files) {
|
foreach my $file (@files) {
|
copy($file,"$verilator/rtl_work/");
|
my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$");
|
|
#print "$path\n";
|
|
my $remove="$target_dir/";
|
|
$path =~ s/$remove//;
|
|
$paths{$path}=1;
|
|
|
|
#put packages at the top of the list
|
|
if(check_file_has_string($file,'endpackage')){
|
|
$pakages.="../${path}${name}$suffix\n" if($platform eq 'modelsim');
|
|
$pakages.="./${name}$suffix\n" if($platform eq 'verilator');
|
|
} else{
|
|
$file_list.= "../${path}${name}$suffix\n"if($platform eq 'modelsim');
|
|
$file_list.= "./${name}$suffix\n"if($platform eq 'verilator');
|
|
}
|
|
}
|
|
foreach my $p (sort keys %paths){
|
|
$include.="+incdir+../$p\n";
|
}
|
}
|
|
|
@files = File::Find::Rule->file()
|
return "$include\n$pakages\n$file_list";
|
->name( '*.sv','*.vh' )
|
|
->in( @ff );
|
|
foreach my $file (@files) {
|
|
copy($file,"$verilator/processed_rtl");
|
|
}
|
}
|
|
|
|
|
|
sub verilator_compilation {
|
|
my ($top_ref,$target_dir,$outtext,$cpu_num)=@_;
|
|
$cpu_num = 1 if (!defined $cpu_num);
|
|
my %tops = %{$top_ref};
|
|
#creat verilator dir
|
|
add_info($outtext,"create verilator dir in $target_dir\n");
|
|
my $verilator="$target_dir/verilator";
|
|
|
#"split all verilog modules in separate files"
|
rmtree("$verilator");
|
add_info(\$outtext,"split all verilog modules in separate files\n");
|
mkpath("$verilator",1,01777);
|
my $split = Verilog::EditFiles->new
|
|
(outdir => "$verilator/processed_rtl",
|
|
translate_synthesis => 0,
|
|
celldefine => 0,
|
|
);
|
|
$split->read_and_split(glob("$verilator/rtl_work/*.v"));
|
|
$split->write_files();
|
|
$split->read_and_split(glob("$verilator/rtl_work/*.sv"));
|
|
$split->write_files();
|
|
|
|
|
my @ff = ("$target_dir/src_verilog");
|
|
push (@ff,"$target_dir/src_verilator") if (-d "$target_dir/src_verilator");
|
|
push (@ff,"$target_dir/src_sim") if (-d "$target_dir/src_sim");
|
|
|
#run verilator
|
#create a file list
|
#my $cmd= "cd \"$verilator/processed_rtl\" \n xterm -e bash -c ' verilator --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3 -CFLAGS -O3'";
|
add_info($outtext,"make a file list containig all RTL modules\n");
|
foreach my $top (sort keys %tops) {
|
my $tt =create_file_list($target_dir,\@ff,'verilator');
|
add_colored_info(\$outtext,"Generate $top Verilator model from $tops{$top} file\n",'green');
|
save_file("$verilator/file_list.f", "$tt");
|
my $cmd= "cd \"$verilator/processed_rtl\" \n verilator --cc $tops{$top} --prefix \"$top\" -O3 -CFLAGS -O3";
|
|
add_info(\$outtext,"$cmd\n");
|
#check if -Wno-TIMESCALEMOD flag is supported"
|
|
my $flag="";
|
|
# my $cmd ="verilator --version | head -n1 | cut -d\" \" -f2";
|
|
# my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
|
|
|
# my $current_v=$stdout;
|
|
# $current_v =~ s/[^0-9.]//g;
|
|
# if (defined $current_v){
|
|
# $cmd = "printf \'%s\n\' \"4.0.0\" \"$current_v\" | sort -V | head -n1";
|
|
# my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
|
# $stdout =~ s/[^0-9.]//g;
|
|
# if ($stdout eq "4.0.0" ){
|
|
# add_info($outtext, "Verilator vesrion $current_v is Greater than or equal to 4.0.0. So compile with -Wno-TIMESCALEMOD flag\n");
|
|
# $flag.="-Wno-TIMESCALEMOD";
|
|
# }else{
|
|
# add_info($outtext, "Verilator vesrion is $current_v\n");
|
|
# }
|
|
# }
|
|
my $pdir = get_project_dir();
|
|
my $tmp = "$pdir/mpsoc/perl_gui/lib/verilog/tmp.v";
|
|
my $cmd = "verilator --lint-only $tmp -Wno-TIMESCALEMOD";
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
if(length $stderr>1){
|
|
add_info(\$outtext,"$stderr\n");
|
if(length $stderr>1){ #-Wno-TIMESCALEMOD not supported
|
|
#add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error.
|
}else {
|
}else {
|
add_info(\$outtext,"$stdout\n");
|
#add_info($outtext,"compile verilator with -Wno-TIMESCALEMOD\n");
|
}
|
$flag.="-Wno-TIMESCALEMOD";
|
}
|
}
|
|
|
|
#run verilator
|
#check if verilator model has been generated
|
my $jobs=0; #a counter to limit the number of paralle process
|
|
my $make_lib="";
|
|
$cmd="cd \"$verilator\"; ";
|
|
my $vrun="#!/bin/bash
|
|
cd \"$verilator\"
|
|
";
|
|
#my $cmd= "cd \"$verilator/processed_rtl\" \n xterm -e bash -c ' verilator --cc $name.v --profile-cfuncs --prefix \"Vtop\" -O3 -CFLAGS -O3'";
|
|
my $length = scalar (keys %tops);
|
foreach my $top (sort keys %tops) {
|
foreach my $top (sort keys %tops) {
|
if (-f "$verilator/processed_rtl/obj_dir/$top.cpp"){#succsess
|
add_colored_info($outtext,"Generate $top Verilator model from $tops{$top} file\n",'green');
|
|
$cmd.= "verilator -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 & ";
|
|
$vrun.="verilator -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 &\n";
|
|
|
|
$make_lib.="make lib$jobs &\n";
|
|
$jobs++;
|
|
|
|
if( $jobs % $cpu_num == 0 || $jobs == $length){
|
|
$vrun.="wait\n"; $make_lib.="wait\n"; $cmd.="wait\n";
|
|
add_info($outtext,"$cmd\n");
|
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
|
if(length $stderr>1){
|
|
add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error.
|
}else {
|
}else {
|
return 0;
|
add_info($outtext,"$stdout\n");
|
}
|
|
}
|
}
|
#generate makefile
|
$cmd="cd \"$verilator\"; ";
|
gen_verilator_makefile($top_ref,"$verilator/processed_rtl/obj_dir/Makefile");
|
|
return 1;
|
|
}
|
}
|
|
|
|
|
sub gen_verilator_makefile{
|
|
my ($top_ref,$target_dir) =@_;
|
|
my %tops = %{$top_ref};
|
|
my $p='';
|
|
my $q='';
|
|
my $h='';
|
|
my $l;
|
|
my $lib_num=0;
|
|
my $all_lib="";
|
|
foreach my $top (sort keys %tops) {
|
|
$p = "$p ${top}__ALL.a ";
|
|
$q = $q."lib$lib_num:\n\t\$(MAKE) -f ${top}.mk\n";
|
|
$h = "$h ${top}.h ";
|
|
$l = $top;
|
|
$all_lib=$all_lib." lib$lib_num";
|
|
$lib_num++;
|
|
}
|
}
|
|
|
|
|
my $make= "
|
|
|
|
default: sim
|
|
|
|
|
|
|
#check if verilator model has been generated
|
|
foreach my $top (sort keys %tops) {
|
|
|
include $l.mk
|
$vrun.="
|
|
if ! [ -f $verilator/obj_dir/$top.cpp ]; then
|
|
echo \"Failed to generate: $verilator/obj_dir/$top.cpp \"
|
|
exit 1
|
|
fi
|
|
";
|
|
|
lib: $all_lib
|
if (-f "$verilator/obj_dir/$top.cpp"){#succsess
|
|
|
$q
|
|
|
|
|
}else {
|
|
return 0;
|
|
}
|
|
}
|
|
#generate makefile
|
|
gen_verilator_makefile($top_ref,"$verilator/obj_dir/Makefile");
|
|
|
#######################################################################
|
$vrun.=" echo \"Verilator modules are generated successfully\".
|
# Compile flags
|
|
|
|
CPPFLAGS += -DVL_DEBUG=1
|
cd $verilator/obj_dir/
|
ifeq (\$(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
|
CPPFLAGS += -DVL_THREADED=1
|
|
CPPFLAGS += -W -Werror -Wall
|
|
endif
|
|
|
|
#######################################################################
|
#run make file
|
# Linking final exe -- presumes have a sim_main.cpp
|
$make_lib
|
|
|
|
make sim
|
|
#done
|
|
";
|
|
|
sim: testbench.o \$(VK_GLOBAL_OBJS) $p
|
|
\$(LINK) \$(LDFLAGS) -g \$^ \$(LOADLIBES) \$(LDLIBS) -o testbench \$(LIBS) -Wall -O3 2>&1 | c++filt
|
|
|
|
testbench.o: testbench.cpp $h
|
save_file ("$verilator/verilate.sh",$vrun);
|
|
#copy topology connection header files
|
|
my $project_dir = get_project_dir();
|
|
$project_dir= "$project_dir/mpsoc";
|
|
my $src_verilator_dir="$project_dir/src_verilator";
|
|
my @files = File::Find::Rule->file()
|
|
->name( '*.h')
|
|
->in( "$src_verilator_dir" );
|
|
copy_file_and_folders (\@files,$project_dir,"$verilator/obj_dir/");
|
|
|
clean:
|
return 1;
|
rm *.o *.a testbench
|
}
|
";
|
|
|
|
save_file ($target_dir,$make);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub verilator_compilation_win {
|
sub verilator_compilation_win {
|
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
|
my $window = def_popwin_size(80,80,"Step 2: Compile",'percent');
|
my $mtable = def_table(10, 10, FALSE);
|
my $mtable = def_table(10, 10, FALSE);
|
my ($outbox,$outtext)= create_text();
|
my ($outbox,$outtext)= create_txview();
|
|
|
|
|
my $next=def_image_button('icons/run.png','Next');
|
my $next=def_image_button('icons/run.png','Next');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $load= show_gif("icons/load.gif");
|
my $load= show_gif("icons/load.gif");
|
Line 1366... |
Line 2122... |
|
|
});
|
});
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
verilator_testbench($self,$name,$top,$target_dir);
|
verilator_testbench($self,$name,$top,$target_dir,$vendor);
|
|
|
});
|
});
|
|
|
$window->add ($mtable);
|
$window->add ($mtable);
|
$window->show_all();
|
$window->show_all();
|
|
|
|
|
my $result;
|
my $result;
|
|
my $cpu_num = $self->object_get_attribute('compile', 'cpu_num');
|
|
|
my $n= $self->object_get_attribute('soc_name',undef);
|
my $n= $self->object_get_attribute('soc_name',undef);
|
if(defined $n){ #we are compiling a single tile as SoC
|
if(defined $n){ #we are compiling a single tile as SoC
|
|
my $sw_path = "$target_dir/sw";
|
|
my %params = soc_get_all_parameters($self);
|
|
my $verilator = soc_generate_verilator ($self,$sw_path,"verilator_$n",\%params);
|
my %tops;
|
my %tops;
|
$tops{"Vtop"}= "$name.v";
|
$tops{"Vtop"}= "--top-module verilator_$n";
|
$result = verilator_compilation (\%tops,$target_dir,$outtext);
|
my $target_verilator_dr ="$target_dir/src_verilator";
|
|
mkpath("$target_verilator_dr",1,01777);
|
|
save_file ("$target_verilator_dr/verilator_${n}.sv",$verilator);
|
|
|
|
|
|
|
|
|
|
|
|
#$tops{"Vtop"}= "--top-module $name";
|
|
$result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num);
|
$self->object_add_attribute('verilator','libs',\%tops);
|
$self->object_add_attribute('verilator','libs',\%tops);
|
}
|
}
|
else { # we are compiling a complete NoC-based mpsoc
|
else { # we are compiling a complete NoC-based mpsoc
|
$result = gen_mpsoc_verilator_model ($self,$name,$top,$target_dir,$outtext);
|
$result = gen_mpsoc_verilator_model ($self,$name,$top,$target_dir,$outtext,$cpu_num);
|
|
|
|
|
}
|
}
|
|
|
|
|
#check if verilator model has been generated
|
#check if verilator model has been generated
|
if ($result){
|
if ($result){
|
add_colored_info(\$outtext,"Veriator model has been generated successfully!",'blue');
|
add_colored_info($outtext,"Veriator model has been generated successfully!",'blue');
|
$load->destroy();
|
$load->destroy();
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
}else {
|
}else {
|
add_colored_info(\$outtext,"Verilator compilation failed!\n","red");
|
add_colored_info($outtext,"Verilator compilation failed!\n","red");
|
$load->destroy();
|
$load->destroy();
|
$next->destroy();
|
$next->destroy();
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
sub gen_mpsoc_verilator_model{
|
sub gen_mpsoc_verilator_model{
|
my ($self,$name,$top,$target_dir,$outtext)=@_;
|
my ($self,$name,$top,$target_dir,$outtext,$cpu_num)=@_;
|
my $dir = Cwd::getcwd();
|
|
my $project_dir = abs_path("$dir/..");
|
my $project_dir = get_project_dir();
|
|
$project_dir= "$project_dir/mpsoc";
|
my $src_verilator_dir="$project_dir/src_verilator";
|
my $src_verilator_dir="$project_dir/src_verilator";
|
my $target_verilog_dr ="$target_dir/src_verilog";
|
my $target_verilog_dr ="$target_dir/src_verilog";
|
my $target_verilator_dr ="$target_dir/src_verilator";
|
my $target_verilator_dr ="$target_dir/src_verilator";
|
|
|
my $sw_dir = "$target_dir/sw";
|
my $sw_dir = "$target_dir/sw";
|
my $src_noc_dir="$project_dir/src_noc";
|
my $src_noc_dir="$project_dir/rtl/src_noc";
|
mkpath("$target_verilator_dr",1,01777);
|
mkpath("$target_verilator_dr",1,01777);
|
|
|
#copy src_verilator files
|
#copy src_verilator files
|
my @files_list = File::Find::Rule->file()
|
my @files_list = File::Find::Rule->file()
|
->name( '*.v','*.V','*.sv' )
|
->name( '*.v','*.V','*.sv' )
|
Line 1455... |
Line 2225... |
$noc_param
|
$noc_param
|
|
|
//simulation parameter
|
//simulation parameter
|
|
|
\n \n \`endif" ;
|
\n \n \`endif" ;
|
save_file("$target_verilator_dr/parameter.v",$noc_param_v);
|
#save_file("$target_verilator_dr/parameter.v",$noc_param_v);
|
|
|
|
|
|
|
|
|
my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self);
|
my ($nr,$ne,$router_p,$ref_tops)= get_noc_verilator_top_modules_info($self);
|
Line 1487... |
Line 2257... |
$y{'EAw'} = $EAw;
|
$y{'EAw'} = $EAw;
|
$y{'RAw'} = $RAw;
|
$y{'RAw'} = $RAw;
|
$y{'Fw'} = $Fw;
|
$y{'Fw'} = $Fw;
|
my @nis=get_NI_instance_list($top);
|
my @nis=get_NI_instance_list($top);
|
$soc->soc_add_instance_param($nis[0] ,\%y );
|
$soc->soc_add_instance_param($nis[0] ,\%y );
|
|
my %z;
|
|
|
|
my %param_type= $soc->soc_get_module_param_type($nis[0]);
|
|
foreach my $p (sort keys %y){
|
|
$z{$p}=$param_type{$p}; #"Parameter";
|
|
}
|
|
|
|
|
|
|
|
|
|
$soc->soc_add_instance_param_type($nis[0] ,\%z );
|
|
|
|
|
my $tile=$tile_num;
|
my $tile=$tile_num;
|
my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile);
|
my $setting=$mpsoc->mpsoc_get_tile_param_setting($tile);
|
my %params;
|
my %params;
|
if ($setting eq 'Custom'){
|
#if ($setting eq 'Custom'){
|
%params= $top->top_get_custom_soc_param($tile);
|
%params= $top->top_get_custom_soc_param($tile);
|
}else{
|
#}else{
|
%params=$top->top_get_default_soc_param();
|
# %params=$top->top_get_default_soc_param();
|
}
|
#}
|
|
|
|
|
my $sw_path = "$sw_dir/tile$tile_num";
|
my $sw_path = "$sw_dir/tile$tile_num";
|
$verilator = $verilator.soc_generate_verilatore ($soc,$sw_path,"tile_$tile",\%params);
|
$verilator = $verilator.soc_generate_verilator ($soc,$sw_path,"tile_$tile",\%params);
|
$tops{"Vtile$tile_num"}= "tile_$tile.v";
|
$tops{"Vtile$tile_num"}= "--top-module tile_$tile";
|
|
|
|
|
}
|
}
|
|
|
save_file ("$target_verilator_dr/verilator_tiles.v",$verilator);
|
save_file ("$target_verilator_dr/verilator_tiles.sv",$verilator);
|
my $result = verilator_compilation (\%tops,$target_dir,$outtext);
|
my $result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num);
|
$self->object_add_attribute('verilator','libs',\%tops);
|
$self->object_add_attribute('verilator','libs',\%tops);
|
return $result;
|
return $result;
|
|
|
}
|
}
|
|
|
Line 1519... |
Line 2301... |
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir)=@_;
|
my $verilator="$target_dir/verilator";
|
my $verilator="$target_dir/verilator";
|
my $dir="$verilator/";
|
my $dir="$verilator/";
|
my $soc_top= $self->soc_get_top ();
|
my $soc_top= $self->soc_get_top ();
|
|
|
|
my $include='#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
';
|
my @intfcs=$soc_top->top_get_intfc_list();
|
my @intfcs=$soc_top->top_get_intfc_list();
|
my %PP;
|
my %PP;
|
|
my %rxds;
|
my $top_port_info="IO type\t port_size\t port_name\n";
|
my $top_port_info="IO type\t port_size\t port_name\n";
|
foreach my $intfc (@intfcs){
|
foreach my $intfc (@intfcs){
|
my $key= ( $intfc eq 'plug:clk[0]')? 'clk' :
|
my $key= ( $intfc eq 'plug:clk[0]')? 'clk' :
|
( $intfc eq 'plug:reset[0]')? 'reset':
|
( $intfc eq 'plug:reset[0]')? 'reset':
|
( $intfc eq 'plug:enable[0]')? 'en' : 'other';
|
( $intfc eq 'plug:enable[0]')? 'en' :
|
|
( $intfc eq 'socket:RxD_sim[0]')? 'rxd':
|
|
'other';
|
|
|
|
|
my $key1="${key}1";
|
my $key1="${key}1";
|
my $key0="${key}0";
|
my $key0="${key}0";
|
|
|
my @ports=$soc_top->top_get_intfc_ports_list($intfc);
|
my @ports=$soc_top->top_get_intfc_ports_list($intfc);
|
foreach my $p (@ports){
|
foreach my $p (@ports){
|
my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
$PP{$key1}= (defined $PP{$key1})? "$PP{$key1} top->$p=1;\n" : "top->$p=1;\n";
|
$PP{$key1}= (defined $PP{$key1})? "$PP{$key1} top->$p=1;\n" : "top->$p=1;\n";
|
$PP{$key0}= (defined $PP{$key0})? "$PP{$key0} top->$p=0;\n" : "top->$p=0;\n";
|
$PP{$key0}= (defined $PP{$key0})? "$PP{$key0} top->$p=0;\n" : "top->$p=0;\n";
|
$top_port_info="$top_port_info $type $range top->$p \n";
|
$top_port_info="$top_port_info $type $range top->$p \n";
|
}
|
}
|
|
if($key eq 'rxd'){
|
|
my @ports=$soc_top->top_get_intfc_ports_list($intfc);
|
|
foreach my $p (@ports){
|
|
my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
|
my @q =split (/RxD_ready_si/,$p);
|
|
$rxds{$id}{p}=$q[0] if( defined $q[1]);
|
|
$rxds{$id}{top}='top' if( defined $q[1]);
|
|
}
|
|
}
|
|
|
}
|
}
|
|
|
|
|
|
my ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir);
|
|
my $include2="";
|
|
$include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0);
|
|
|
my $main_c=get_license_header("testbench.cpp");
|
my $main_c=get_license_header("testbench.cpp");
|
|
|
|
|
|
|
$main_c="$main_c
|
$main_c="$main_c
|
#include <stdlib.h>
|
$include
|
#include <stdio.h>
|
$include1
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <verilated.h> // Defines common routines
|
#include <verilated.h> // Defines common routines
|
#include \"Vtop.h\" // From Verilating \"$name.v\" file
|
#include \"Vtop.h\" // From Verilating \"$name.v\" file
|
|
|
Vtop *top;
|
Vtop *top;
|
|
$include2
|
/*
|
/*
|
$top_port_info
|
$top_port_info
|
*/
|
*/
|
|
|
|
|
|
|
int reset,clk;
|
int reset,clk;
|
unsigned int main_time = 0; // Current simulation time
|
unsigned int main_time = 0; // Current simulation time
|
|
|
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
|
$rxd_info
|
Verilated::commandArgs(argc, argv); // Remember args
|
Verilated::commandArgs(argc, argv); // Remember args
|
top = new Vtop;
|
top = new Vtop;
|
|
|
/********************
|
/********************
|
* initialize input
|
* initialize input
|
Line 1569... |
Line 2379... |
$PP{reset1}
|
$PP{reset1}
|
$PP{en1}
|
$PP{en1}
|
main_time=0;
|
main_time=0;
|
printf(\"Start Simulation\\n\");
|
printf(\"Start Simulation\\n\");
|
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
|
$rxd_cap_cal
|
|
if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle
|
if (main_time >= 10 ) {
|
if (main_time >= 10 ) {
|
$PP{reset0}
|
$PP{reset0}
|
}
|
}
|
|
|
|
|
if ((main_time & 1) == 0) {
|
if ((main_time & 1) == 0) {
|
$PP{clk1} // Toggle clock
|
$PP{clk1} // Toggle clock
|
// you can change the inputs and read the outputs here in case they are captured at posedge of clock
|
// you can change the inputs and read the outputs here in case they are captured at posedge of clock
|
|
$rxd_wr_cal
|
|
|
|
|
}//if
|
}//if
|
else
|
else
|
{
|
{
|
Line 1614... |
Line 2425... |
my $path=$mpsoc->object_get_attribute('setting','soc_path');
|
my $path=$mpsoc->object_get_attribute('setting','soc_path');
|
$path=~ s/ /\\ /g;
|
$path=~ s/ /\\ /g;
|
my $p = "$path/$soc_name.SOC";
|
my $p = "$path/$soc_name.SOC";
|
my ($soc,$r,$err) = regen_object($p);
|
my ($soc,$r,$err) = regen_object($p);
|
if ($r){
|
if ($r){
|
show_info(\$outtext,"**Error reading $p file: $err\n");
|
show_info($outtext,"**Error reading $p file: $err\n");
|
next;
|
next;
|
}
|
}
|
return $soc;
|
return $soc;
|
}
|
}
|
|
|
|
sub rxd_testbench_verilator_gen {
|
|
my ($rxds_ref,$dir)=@_;
|
|
|
|
my $rxd_info='';
|
|
my $rxd_num=0;
|
|
my $rxd_func='';
|
|
my $rxd_wr_cal='';
|
|
my $rxd_cap_cal='';
|
|
my $include='';
|
|
|
|
my %rxds=%{$rxds_ref};
|
|
|
|
foreach my $rxd (sort keys %rxds){
|
|
my $n=$rxds{$rxd}{p};
|
|
my $top=$rxds{$rxd}{top};
|
|
$rxd_info.="\\t$rxd_num : ${top}_${n}RXD\\n";
|
|
|
|
$rxd_func.="
|
|
// we have a character to send to interface $rxd_num
|
|
if (sent_table[$rxd_num]!=0 && $top->${n}RxD_ready_sim){
|
|
$top->${n}RxD_din_sim=sent_table[$rxd_num];
|
|
$top->${n}RxD_wr_sim=1;
|
|
sent_table[$rxd_num]=0;
|
|
}else {
|
|
$top->${n}RxD_wr_sim=0;
|
|
}
|
|
";
|
|
$rxd_num++;
|
|
}
|
|
|
|
|
|
|
|
if($rxd_num>0){
|
|
$rxd_func="
|
|
#ifndef RXD_SIM_H
|
|
#define RXD_SIM_H
|
|
#define RXD_NUM $rxd_num // number of rxd input interfaces
|
|
char sent_table[RXD_NUM]={0};
|
|
unsigned char active_rxd_num=0;
|
|
void write_char_on_RXD( ) {
|
|
$rxd_func
|
|
}
|
|
|
|
int kbhit(void) {
|
|
struct termios oldt, newt;
|
|
int ch;
|
|
int oldf;
|
|
|
|
tcgetattr(STDIN_FILENO, &oldt);
|
|
newt = oldt;
|
|
newt.c_lflag &= ~(ICANON | ECHO);
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
|
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
|
|
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
|
|
|
|
ch = getchar();
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
|
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
|
|
|
if(ch != EOF)
|
|
{
|
|
ungetc(ch, stdin);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void capture_char_on_RXD (){
|
|
char c;
|
|
if(kbhit()){
|
|
c=getchar();
|
|
if(c=='+'){
|
|
active_rxd_num++;
|
|
if(active_rxd_num>=$rxd_num) active_rxd_num=0;
|
|
printf(\"The active input interface num is \%u\\n\",active_rxd_num);
|
|
}else if(c=='-'){
|
|
active_rxd_num--;
|
|
if(active_rxd_num>=$rxd_num) active_rxd_num=($rxd_num-1);
|
|
printf(\"The active input interface num is \%u\\n\",active_rxd_num);
|
|
}else{
|
|
sent_table[active_rxd_num]=c;
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
";
|
|
|
|
|
|
$include .='#include <termios.h>
|
|
#include <fcntl.h>
|
|
';
|
|
$rxd_wr_cal="write_char_on_RXD( );";
|
|
$rxd_cap_cal="capture_char_on_RXD( );";
|
|
$rxd_info="printf(\"There are total of $rxd_num RXD (UART) interface ports in the top module:\\n${rxd_info}The default interfce is 0. You can switch to different interfaces by pressing + or - key.\\n\");"
|
|
}
|
|
|
|
my $rxsim_c=get_license_header("RxDsim.h");
|
|
$rxsim_c.="$rxd_func";
|
|
save_file("$dir/RxDsim.h",$rxsim_c) if($rxd_num > 0);
|
|
|
|
return ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include);
|
|
|
|
}
|
|
|
|
|
|
|
sub gen_verilator_mpsoc_testbench {
|
sub gen_verilator_mpsoc_testbench {
|
my ($mpsoc,$name,$top,$target_dir,$tview)=@_;
|
my ($mpsoc,$name,$top,$target_dir,$tview)=@_;
|
my $verilator="$target_dir/verilator";
|
my $verilator="$target_dir/verilator";
|
my $dir="$verilator/";
|
my $dir="$verilator/";
|
my $parameter_h=gen_noc_param_h($mpsoc);
|
my $parameter_h=gen_noc_param_h($mpsoc);
|
|
|
|
|
my ($nr,$ne,$router_p,$ref_tops,$includ_h)= get_noc_verilator_top_modules_info($mpsoc);
|
my ($nr,$ne,$router_p,$ref_tops,$includ_h)= get_noc_verilator_top_modules_info($mpsoc);
|
|
|
|
$parameter_h.="
|
|
#define NE $ne
|
|
#define NR $nr
|
|
";
|
$parameter_h=$parameter_h.$includ_h;
|
$parameter_h=$parameter_h.$includ_h;
|
|
|
|
|
|
|
my $libh="";
|
my $libh="";
|
Line 1654... |
Line 2578... |
my $tile_reset="";
|
my $tile_reset="";
|
my $tile_clk="";
|
my $tile_clk="";
|
my $tile_en="";
|
my $tile_en="";
|
my $top_port_info="IO type\t port_size\t port_name\n";
|
my $top_port_info="IO type\t port_size\t port_name\n";
|
my $no_connected='';
|
my $no_connected='';
|
|
my %rxds;
|
|
|
|
my $tile_chans="";
|
|
my $tmp_reg='';
|
for (my $endp=0; $endp<$ne;$endp++){
|
for (my $endp=0; $endp<$ne;$endp++){
|
|
|
|
|
my $e_addr=endp_addr_encoder($mpsoc,$endp);
|
my $e_addr=endp_addr_encoder($mpsoc,$endp);
|
my $router_num = get_connected_router_id_to_endp($mpsoc,$endp);
|
my $router_num = get_connected_router_id_to_endp($mpsoc,$endp);
|
my $r_addr=router_addr_encoder($mpsoc,$router_num);
|
my $r_addr=router_addr_encoder($mpsoc,$router_num);
|
|
|
|
|
Line 1678... |
Line 2606... |
if ($category eq 'NoC') {
|
if ($category eq 'NoC') {
|
$ni_name= $soc->soc_get_instance_name($id);
|
$ni_name= $soc->soc_get_instance_name($id);
|
}
|
}
|
}
|
}
|
|
|
|
$tile_chans.="\ttile_chan_out[$endp] = &tile$endp->ni_chan_out;\n\ttile_chan_in[$endp] = &tile$endp->ni_chan_in;\n";
|
$libh=$libh."#include \"Vtile${endp}.h\"\n";
|
$libh=$libh."#include \"Vtile${endp}.h\"\n";
|
$inst=$inst."Vtile${endp}\t*tile${endp};\t // Instantiation of tile${endp}\n";
|
$inst=$inst."Vtile${endp}\t*tile${endp};\t // Instantiation of tile${endp}\n";
|
$newinst = $newinst."\ttile${endp}\t=\tnew Vtile${endp};\n";
|
$newinst = $newinst."\ttile${endp}\t=\tnew Vtile${endp};\n";
|
$tile_flit_in = $tile_flit_in . "\ttile${endp}->${ni_name}_flit_in = noc->ni_flit_out [${endp}];\n";
|
$tile_flit_in = $tile_flit_in . "\ttile${endp}->${ni_name}_flit_in = noc->ni_flit_out [${endp}];\n";
|
$tile_flit_in_l = $tile_flit_in_l . "\t\ttile${endp}->${ni_name}_flit_in[j] = noc->ni_flit_out [${endp}][j];\n";
|
$tile_flit_in_l = $tile_flit_in_l . "\t\ttile${endp}->${ni_name}_flit_in[j] = noc->ni_flit_out [${endp}][j];\n";
|
Line 1700... |
Line 2628... |
|
|
foreach my $intfc (@intfcs){
|
foreach my $intfc (@intfcs){
|
my $key=($intfc eq 'plug:clk[0]')? 'clk' :
|
my $key=($intfc eq 'plug:clk[0]')? 'clk' :
|
($intfc eq 'plug:reset[0]')? 'reset':
|
($intfc eq 'plug:reset[0]')? 'reset':
|
($intfc eq 'plug:enable[0]')? 'en' :
|
($intfc eq 'plug:enable[0]')? 'en' :
|
|
($intfc eq 'socket:RxD_sim[0]')? 'rxd':
|
'other';
|
'other';
|
|
|
my @ports=$soc_top->top_get_intfc_ports_list($intfc);
|
my @ports=$soc_top->top_get_intfc_ports_list($intfc);
|
foreach my $p (@ports){
|
foreach my $p (@ports){
|
my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
my($inst,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
Line 1711... |
Line 2640... |
$tile_clk=$tile_clk."\t\ttile${endp}->$p=clk;\n" if $key eq 'clk';
|
$tile_clk=$tile_clk."\t\ttile${endp}->$p=clk;\n" if $key eq 'clk';
|
$tile_en=$tile_en."\t\ttile${endp}->$p=enable;\n" if $key eq 'en'; ;
|
$tile_en=$tile_en."\t\ttile${endp}->$p=enable;\n" if $key eq 'en'; ;
|
$top_port_info="$top_port_info $type $range tile${endp}->$p \n";
|
$top_port_info="$top_port_info $type $range tile${endp}->$p \n";
|
}#ports
|
}#ports
|
|
|
|
if($key eq 'rxd'){
|
|
my @ports=$soc_top->top_get_intfc_ports_list($intfc);
|
|
foreach my $p (@ports){
|
|
my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
|
my @q =split (/RxD_ready_si/,$p);
|
|
$rxds{$endp.$id}{p}=$q[0] if( defined $q[1]);
|
|
$rxds{$endp.$id}{top}="tile$endp" if( defined $q[1]);
|
|
}
|
|
}
|
|
|
|
|
}#interface
|
}#interface
|
|
|
$tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_r_addr=$r_addr; // noc->er_addr[${endp}];\n";
|
$tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_r_addr=$r_addr; // noc->er_addr[${endp}];\n";
|
$tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_e_addr=$e_addr;\n";
|
$tile_addr= $tile_addr."\ttile${endp}->${ni_name}_current_e_addr=$e_addr;\n";
|
|
|
}else{
|
}else{
|
#this tile is not connected to any ip. the noc input ports will be connected to ground
|
#this tile is not connected to any ip. the noc input ports will be connected to ground
|
$no_connected=$no_connected."\n // Tile:$endp ($e_addr) is not assigned to any ip\n";
|
$tmp_reg.="\tunsigned char tmp1 [1024]={0};\n \tunsigned char tmp2 [1024]={0};";
|
$no_connected=$no_connected."\t\tnoc->ni_credit_in[${endp}]=0; \n";
|
$tile_chans.="\n // Tile:$endp ($e_addr) is not assigned to any ip. Connet coresponding chan to ground.\n";
|
|
$tile_chans.="\ttile_chan_out[$endp] = tmp1;\n\ttile_chan_in[$endp] = tmp2;\n";
|
|
|
}
|
}
|
|
|
|
|
}
|
}
|
|
|
|
my ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir);
|
|
my $include2="";
|
|
$include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0);
|
|
|
my $main_c=get_license_header("testbench.cpp");
|
my $main_c=get_license_header("testbench.cpp");
|
|
|
$main_c="$main_c
|
$main_c="$main_c
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <string.h>
|
#include <string.h>
|
|
$include1
|
#include <verilated.h> // Defines common routines
|
#include <verilated.h> // Defines common routines
|
|
$tmp_reg
|
|
|
|
|
#include \"Vnoc.h\"
|
|
$libh
|
$libh
|
|
|
Vnoc *noc;
|
|
$inst
|
$inst
|
int reset,clk,enable;
|
int reset,clk,enable;
|
|
|
|
|
#include \"parameter.h\"
|
#include \"parameter.h\"
|
|
void * tile_chan_out[NE];
|
|
void * tile_chan_in[NE];
|
|
|
|
|
/*
|
|
$top_port_info
|
|
*/
|
|
|
|
|
|
unsigned int main_time = 0; // Current simulation time
|
|
|
|
void update_all_instances_inputs(void);
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
int i,j,x,y;
|
|
|
|
Verilated::commandArgs(argc, argv); // Remember args
|
|
Vrouter_new(); // Create instance
|
|
noc = new Vnoc;
|
|
$newinst
|
|
|
|
/********************
|
|
* initialize input
|
|
*********************/
|
|
|
|
|
|
reset=1;
|
#define CHAN_SIZE sizeof(tile0->ni_chan_in)
|
enable=1;
|
|
$no_connected
|
|
|
|
$tile_addr
|
#define conect_r2r(T1,r1,p1,T2,r2,p2) \\
|
|
memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE )
|
|
|
|
#define connect_r2gnd(T,r,p)\\
|
|
memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE)
|
|
|
main_time=0;
|
#define connect_r2e(T,r,p,e) \\
|
printf(\"Start Simulation\\n\");
|
memcpy(&router##T [r]->chan_in[p], tile_chan_out[e], CHAN_SIZE );\\
|
while (!Verilated::gotFinish()) {
|
memcpy(tile_chan_in[e], &router##T [r]->chan_out[p], CHAN_SIZE )
|
|
|
if (main_time >= 10 ) {
|
|
reset=0;
|
|
}
|
|
|
|
|
|
if ((main_time % 5) == 0) {
|
#include \"topology_top.h\"
|
clk = 1; // Toggle clock
|
$include2
|
// you can change the inputs and read the outputs here in case they are captured at posedge of clock
|
|
|
|
}
|
/*
|
else{
|
$top_port_info
|
clk = 0; // Toggle clock
|
*/
|
update_all_instances_inputs();
|
|
|
|
|
|
|
unsigned int main_time = 0; // Current simulation time
|
|
|
}
|
|
|
|
|
|
|
void connect_clk_reset_en_all(void){
|
//clk,reset,enable
|
//clk,reset,enable
|
noc-> clk = clk;
|
|
noc-> reset = reset;
|
|
$tile_reset
|
$tile_reset
|
$tile_clk
|
$tile_clk
|
$tile_en
|
$tile_en
|
|
|
connect_routers_reset_clk();
|
connect_routers_reset_clk();
|
|
}
|
|
|
//eval instances
|
void sim_eval_all(void){
|
noc->eval();
|
|
routers_eval();
|
routers_eval();
|
|
|
$tile_eval
|
$tile_eval
|
|
}
|
|
|
|
void sim_final_all(void ){
|
main_time++;
|
|
|
|
|
|
|
|
}//while
|
|
|
|
// Simulation is done
|
|
routers_final();
|
routers_final();
|
noc->final();
|
|
$tile_final
|
$tile_final
|
}
|
}
|
|
|
double sc_time_stamp () { // Called by \$time in Verilog
|
void clk_posedge_event(void) {
|
return main_time;
|
|
}
|
|
|
|
|
clk = 1; // Toggle clock
|
|
// you can change the inputs and read the outputs here in case they are captured at posedge of clock
|
|
$rxd_wr_cal
|
|
connect_clk_reset_en_all();
|
|
sim_eval_all();
|
|
}
|
|
|
void update_all_instances_inputs(void){
|
|
|
|
int x,y,i,j;
|
void clk_negedge_event(void){
|
|
|
|
clk = 0;
|
|
topology_connect_all_nodes ();
|
|
connect_clk_reset_en_all();
|
|
sim_eval_all();
|
|
}
|
|
|
#if (NC<=64)
|
|
noc->ni_flit_in_wr =0;
|
|
#else
|
|
for(j=0;j<(sizeof(noc->ni_flit_in_wr)/sizeof(noc->ni_flit_in_wr[0])); j++) noc->ni_flit_in_wr[j]=0;
|
|
#endif
|
|
|
|
connect_all_routers_to_noc ();
|
int main(int argc, char** argv) {
|
|
int i,j,x,y;
|
|
$rxd_info
|
|
Verilated::commandArgs(argc, argv); // Remember args
|
|
Vrouter_new(); // Create instance
|
|
|
|
$newinst
|
|
|
#if (Fpay<=32)
|
/********************
|
//tile[i]->flit_in = noc->ni_flit_out [i];
|
* initialize input
|
$tile_flit_in
|
*********************/
|
#else
|
$tile_chans
|
for(j=0;j<(sizeof(traffic[i]->flit_out)/sizeof(traffic[i]->flit_out[0])); j++){
|
|
//traffic[i]->flit_in[j] = noc->ni_flit_out [i][j];
|
|
$tile_flit_in_l
|
|
}
|
|
#endif
|
|
|
|
//traffic[i]->credit_in= noc->ni_credit_out[i];
|
reset=1;
|
$tile_credit
|
enable=1;
|
|
topology_init();
|
|
|
//noc->ni_credit_in[i] = traffic[i]->credit_out;
|
$no_connected
|
$noc_credit
|
|
|
|
#if (Fpay<=32)
|
$tile_addr
|
//noc->ni_flit_in [i] = traffic[i]->flit_out;
|
|
$noc_flit_in
|
|
|
|
#else
|
|
for(j=0;j<(sizeof(traffic[i]->flit_out)/sizeof(traffic[i]->flit_out[0])); j++){
|
|
//noc->ni_flit_in [i][j] = traffic[i]->flit_out[j];
|
|
$noc_flit_in_l
|
|
}
|
|
#endif
|
|
|
|
|
|
#if (NC<=64)
|
main_time=0;
|
//if(traffic[i]->flit_out_wr) noc->ni_flit_in_wr = noc->ni_flit_in_wr | ((vluint64_t)1<<i);
|
printf(\"Start Simulation\\n\");
|
$noc_flit_in_wr
|
while (!Verilated::gotFinish()) {
|
|
$rxd_cap_cal
|
//traffic[i]->flit_in_wr= ((noc->ni_flit_out_wr >> i) & 0x01);
|
if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle
|
$tile_flit_in_wr
|
if (main_time >= 10 ) reset=0;
|
#else
|
|
//if(traffic[i]->flit_out_wr) MY_VL_SETBIT_W(noc->ni_flit_in_wr ,i);
|
clk_posedge_event( );
|
$noc_flit_in_wr_l
|
//The valus of all registers and input ports valuse change @ posedge of the clock. Once clk is deasserted, as multiple modules are connected inside the testbench we need several eval for propogating combinational logic values
|
|
//between modules when the clock .
|
|
for (i=0;i<2*(SMART_MAX+1);i++) clk_negedge_event( );
|
|
|
//traffic[i]->flit_in_wr= (VL_BITISSET_W(noc->ni_flit_out_wr,i)>0);
|
main_time++;
|
$tile_flit_in_wr_l
|
}//while
|
|
|
#endif
|
// Simulation is done
|
|
sim_final_all();
|
|
}
|
|
|
|
double sc_time_stamp () { // Called by \$time in Verilog
|
|
return main_time;
|
|
}
|
|
|
|
|
}
|
|
";
|
";
|
|
|
save_file("$dir/parameter.h",$parameter_h);
|
save_file("$dir/parameter.h",$parameter_h);
|
save_file("$dir/testbench.cpp",$main_c);
|
save_file("$dir/testbench.cpp",$main_c);
|
|
|
Line 1911... |
Line 2825... |
|
|
my $module =$soc->soc_get_module($id);
|
my $module =$soc->soc_get_module($id);
|
my $category =$soc->soc_get_category($id);
|
my $category =$soc->soc_get_category($id);
|
my $inst = $soc->soc_get_instance_name($id);
|
my $inst = $soc->soc_get_instance_name($id);
|
my %params = $soc->soc_get_module_param($id);
|
my %params = $soc->soc_get_module_param($id);
|
|
my %params_type = $soc->soc_get_module_param_type($id);
|
my $ip = ip->lib_new ();
|
my $ip = ip->lib_new ();
|
my @param_order=$soc->soc_get_instance_param_order($id);
|
my @param_order=$soc->soc_get_instance_param_order($id);
|
|
|
foreach my $p (sort keys %params){
|
foreach my $p (sort keys %params){
|
my $inst_param= "$inst\_$p";
|
my $inst_param= "$inst\_$p";
|
#add instance name to parameter value
|
#add instance name to parameter value
|
$params{$p}=add_instantc_name_to_parameters(\%params,$inst,$params{$p});
|
$params{$p}=add_instantc_name_to_parameters(\%params,$inst,$params{$p});
|
my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p);
|
my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p);
|
|
|
$vfile_param_type= "Don't include" if (!defined $vfile_param_type );
|
$vfile_param_type= "Don't include" if (!defined $vfile_param_type );
|
$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
if ($vfile_param_type eq "Localparam"){
|
$vfile_param_type= "Localparam" if ($vfile_param_type eq 0);
|
my $type = $params_type{$p};
|
|
$type = "Localparam" if (! defined $type);
|
|
$vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam";
|
|
}
|
|
|
|
#$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
|
#$vfile_param_type= "Localparam" if ($vfile_param_type eq 0);
|
$all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" );
|
$all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" );
|
#print"$all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq \"Parameter\" || $vfile_param_type eq \"Localparam\" ); \n";
|
#print"$all_param{ $inst_param} = $params{ $p} if($vfile_param_type eq \"Parameter\" || $vfile_param_type eq \"Localparam\" ); \n";
|
}
|
}
|
}
|
}
|
return %all_param;
|
return %all_param;
|
Line 1939... |
Line 2861... |
foreach my $id (@instances){
|
foreach my $id (@instances){
|
my $module =$soc->soc_get_module($id);
|
my $module =$soc->soc_get_module($id);
|
my $category =$soc->soc_get_category($id);
|
my $category =$soc->soc_get_category($id);
|
my $inst = $soc->soc_get_instance_name($id);
|
my $inst = $soc->soc_get_instance_name($id);
|
my @order = $soc->soc_get_instance_param_order($id);
|
my @order = $soc->soc_get_instance_param_order($id);
|
|
my %params_type = $soc->soc_get_module_param_type($id);
|
foreach my $p ( @order){
|
foreach my $p ( @order){
|
my $inst_param= "$inst\_$p";
|
my $inst_param= "$inst\_$p";
|
my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p);
|
my ($default,$type,$content,$info,$vfile_param_type,$redefine_param)= $ip->ip_get_parameter($category,$module,$p);
|
$vfile_param_type= "Don't include" if (!defined $vfile_param_type );
|
$vfile_param_type= "Don't include" if (!defined $vfile_param_type );
|
$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
if ($vfile_param_type eq "Localparam"){
|
$vfile_param_type= "Localparam" if ($vfile_param_type eq 0);
|
my $type = $params_type{$p};
|
|
$type = "Localparam" if (! defined $type);
|
|
$vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam";
|
|
}
|
|
#$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
|
#$vfile_param_type= "Localparam" if ($vfile_param_type eq 0);
|
push(@all_order, $inst_param) if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" );
|
push(@all_order, $inst_param) if($vfile_param_type eq "Parameter" || $vfile_param_type eq "Localparam" );
|
}
|
}
|
}
|
}
|
return @all_order;
|
return @all_order;
|
}
|
}
|
|
|
|
|
|
|
sub gen_modelsim_soc_testbench {
|
sub gen_modelsim_soc_testbench {
|
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir,$tview)=@_;
|
my $dir="$target_dir/src_verilog";
|
my $dir="$target_dir/Modelsim";
|
my $soc_top= $self->object_get_attribute('top_ip',undef);
|
my $soc_top= $self->object_get_attribute('top_ip',undef);
|
|
|
my @intfcs=$soc_top->top_get_intfc_list();
|
my @intfcs=$soc_top->top_get_intfc_list();
|
my %PP;
|
my %PP;
|
my $top_port_def="// ${name}.v IO definition \n";
|
my $top_port_def="// ${name}.v IO definition \n";
|
my $pin_assign;
|
my $pin_assign;
|
my $rst_inputs='';
|
my $rst_inputs='';
|
|
|
|
|
|
|
|
|
#add functions
|
#add functions
|
my $d = Cwd::getcwd();
|
my $project_dir = get_project_dir();
|
open my $file1, "<", "$d/lib/verilog/functions.v" or die;
|
open my $file1, "<", "$project_dir/mpsoc/perl_gui/lib/verilog/functions.v" or die;
|
my $functions_all='';
|
my $functions_all='';
|
while (my $f1 = readline ($file1)) {
|
while (my $f1 = readline ($file1)) {
|
$functions_all="$functions_all $f1 ";
|
$functions_all="$functions_all $f1 ";
|
}
|
}
|
close($file1);
|
close($file1);
|
Line 2037... |
Line 2965... |
if($type eq 'input'){
|
if($type eq 'input'){
|
$top_port_def="$top_port_def reg $range $p;\n"
|
$top_port_def="$top_port_def reg $range $p;\n"
|
}else{
|
}else{
|
$top_port_def="$top_port_def wire $range $p;\n"
|
$top_port_def="$top_port_def wire $range $p;\n"
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$pin_assign=(defined $pin_assign)? "$pin_assign,\n\t\t.$p($p)": "\t\t.$p($p)";
|
$pin_assign=(defined $pin_assign)? "$pin_assign,\n\t\t.$p($p)": "\t\t.$p($p)";
|
$rst_inputs= "$rst_inputs $p=0;\n" if ($key eq 'other' && $type eq 'input' );
|
$rst_inputs= "$rst_inputs $p=0;\n" if ($key eq 'other' && $type eq 'input' );
|
}
|
}
|
|
|
|
|
}
|
}
|
|
my $global_localparam=get_golal_param_v();
|
my $test_v= get_license_header("testbench.v");
|
my $test_v= get_license_header("testbench.v");
|
|
|
|
my $mpsoc_name=$self->object_get_attribute('mpsoc_name');
|
|
#if(defined $mpsoc_name){
|
|
if(0){
|
|
|
|
|
|
my $top_ip=ip_gen->top_gen_new();
|
|
my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name";
|
|
my $hw_dir = "$target_dir/src_verilog";
|
|
my $sw_dir = "$target_dir/sw";
|
|
my ($socs_v,$io_short,$io_full,$top_io_short,$top_io_full,$top_io_pass,$href)=gen_socs_v($self,$top_ip,$sw_dir,$tview);
|
|
my $socs_param= gen_socs_param($self);
|
|
my $global_localparam=get_golal_param_v();
|
|
my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($self);
|
|
|
|
|
|
$test_v.="
|
|
|
|
$clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port
|
|
|
|
`timescale 1ns/1ps
|
|
|
|
module testbench;
|
|
|
|
$functions_all
|
|
|
|
$global_localparam
|
|
|
|
$socs_param
|
|
|
|
$top_port_def
|
|
|
|
|
|
\t${mpsoc_name} the_${mpsoc_name} (
|
|
$top_io_pass
|
|
|
|
\t);
|
|
/*****************************************************************/
|
|
";
|
|
|
|
|
|
}
|
|
|
$test_v ="$test_v
|
$test_v ="$test_v
|
|
|
`timescale 1ns/1ps
|
`timescale 1ns/1ps
|
|
|
module testbench;
|
module testbench;
|
|
|
$functions_all
|
$functions_all
|
|
|
|
$global_localparam
|
|
|
$params_v
|
$params_v
|
|
|
$top_port_def
|
$top_port_def
|
|
|
|
|
Line 2098... |
Line 3078... |
|
|
|
|
}
|
}
|
|
|
sub verilator_testbench{
|
sub verilator_testbench{
|
my ($self,$name,$top,$target_dir)=@_;
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
my $verilator="$target_dir/verilator";
|
my $verilator="$target_dir/verilator";
|
my $dir="$verilator";
|
my $dir="$verilator";
|
|
|
my ($app,$table,$tview,$window) = software_main($dir,'testbench.cpp');
|
my ($app,$table,$tview,$window) = software_main($dir,'testbench.cpp');
|
|
|
Line 2114... |
Line 3094... |
gen_verilator_mpsoc_testbench (@_,$tview) if((-f "$dir/testbench.cpp")==0);
|
gen_verilator_mpsoc_testbench (@_,$tview) if((-f "$dir/testbench.cpp")==0);
|
|
|
}
|
}
|
|
|
#copy makefile
|
#copy makefile
|
#copy("../script/verilator_soc_make", "$verilator/processed_rtl/obj_dir/Makefile");
|
#copy("../script/verilator_soc_make", "$verilator/obj_dir/Makefile");
|
|
|
|
|
|
|
|
|
|
|
Line 2135... |
Line 3115... |
$table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
|
$table->attach ($run,9, 10, 1,2,'shrink','shrink',0,0);
|
|
|
$back-> signal_connect("clicked" => sub{
|
$back-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
verilator_compilation_win($self,$name,$top,$target_dir);
|
verilator_compilation_win($self,$name,$top,$target_dir,$vendor);
|
|
|
});
|
});
|
|
|
$regen-> signal_connect("clicked" => sub{
|
$regen-> signal_connect("clicked" => sub{
|
my $dialog = Gtk2::MessageDialog->new (my $window,
|
my $response = yes_no_dialog("Are you sure you want to regenerate the testbench.cpp file? Note that any changes you have made will be lost");
|
'destroy-with-parent',
|
|
'question', # message type
|
|
'yes-no', # which set of buttons?
|
|
"Are you sure you want to regenaret the testbench.cpp file? Note that any changes you have made will be lost");
|
|
my $response = $dialog->run;
|
|
if ($response eq 'yes') {
|
if ($response eq 'yes') {
|
my $n= $self->object_get_attribute('soc_name',undef);
|
my $n= $self->object_get_attribute('soc_name',undef);
|
if(defined $n){ #we are compiling a single tile as SoC
|
if(defined $n){ #we are compiling a single tile as SoC
|
gen_verilator_soc_testbench ($self,$name,$top,$target_dir);
|
gen_verilator_soc_testbench ($self,$name,$top,$target_dir);
|
}
|
}
|
else { # we are compiling a complete NoC-based mpsoc
|
else { # we are compiling a complete NoC-based mpsoc
|
gen_verilator_mpsoc_testbench ($self,$name,$top,$target_dir,$tview);
|
gen_verilator_mpsoc_testbench ($self,$name,$top,$target_dir,$tview);
|
|
|
}
|
}
|
|
|
$app->load_source("$dir/testbench.cpp");
|
$app->refresh_source("$dir/testbench.cpp");
|
}
|
}
|
$dialog->destroy;
|
|
|
|
});
|
});
|
|
|
|
|
$make -> signal_connect("clicked" => sub{
|
$make -> signal_connect("clicked" => sub{
|
$make->hide_all;
|
$make->hide;
|
my $load= show_gif("icons/load.gif");
|
my $load= show_gif("icons/load.gif");
|
$table->attach ($load,8, 9, 1,2,'shrink','shrink',0,0);
|
$table->attach ($load,8, 9, 1,2,'shrink','shrink',0,0);
|
$table->show_all;
|
$table->show_all;
|
$app->do_save();
|
$app->ask_to_save_changes();
|
copy("$dir/testbench.cpp", "$verilator/processed_rtl/obj_dir/testbench.cpp");
|
copy("$dir/testbench.cpp", "$verilator/obj_dir/testbench.cpp");
|
copy("$dir/parameter.h", "$verilator/processed_rtl/obj_dir/parameter.h") if(-f "$dir/parameter.h");
|
copy("$dir/parameter.h", "$verilator/obj_dir/parameter.h") if(-f "$dir/parameter.h");
|
|
copy("$dir/RxDsim.h", "$verilator/obj_dir/RxDsim.h") if(-f "$dir/RxDsim.h");
|
|
|
my $tops_ref=$self->object_get_attribute('verilator','libs');
|
my $tops_ref=$self->object_get_attribute('verilator','libs');
|
my %tops=%{$tops_ref};
|
my %tops=%{$tops_ref};
|
my $lib_num=0;
|
my $lib_num=0;
|
|
my $cpu_num = $self->object_get_attribute('compile', 'cpu_num');
|
|
$cpu_num = 1 if (!defined $cpu_num);
|
|
add_colored_info($tview,"Makefie will use the maximum number of $cpu_num core(s) in parallel for compilation\n",'green');
|
|
my $length=scalar (keys %tops);
|
|
my $cmd="";
|
foreach my $top (sort keys %tops) {
|
foreach my $top (sort keys %tops) {
|
run_make_file("$verilator/processed_rtl/obj_dir/",$tview,"lib$lib_num");
|
$cmd.= "lib$lib_num & ";
|
$lib_num++;
|
$lib_num++;
|
|
if( $lib_num % $cpu_num == 0 || $lib_num == $length){
|
|
$cmd.="wait\n";
|
|
run_make_file("$verilator/obj_dir/",$tview,$cmd);
|
|
$cmd="";
|
|
}else {
|
|
$cmd.=" make ";
|
}
|
}
|
run_make_file("$verilator/processed_rtl/obj_dir/",$tview,"sim");
|
}
|
|
|
|
|
|
#foreach my $top (sort keys %tops) {
|
|
# run_make_file("$verilator/obj_dir/",$tview,"lib$lib_num");
|
|
# $lib_num++;
|
|
#}
|
|
|
|
|
|
|
|
run_make_file("$verilator/obj_dir/",$tview,"sim");
|
$load->destroy;
|
$load->destroy;
|
$make->show_all;
|
$make->show_all;
|
|
|
});
|
});
|
|
|
$run -> signal_connect("clicked" => sub{
|
$run -> signal_connect("clicked" => sub{
|
my $bin="$verilator/processed_rtl/obj_dir/testbench";
|
my $bin="$verilator/obj_dir/testbench";
|
if (-f $bin){
|
if (-f $bin){
|
my $cmd= "cd \"$verilator/processed_rtl/obj_dir/\" \n xterm -e bash -c $bin";
|
my $cmd= "cd \"$verilator/obj_dir/\" \n xterm -e bash -c \"$bin; sleep 5\"";
|
add_info(\$tview,"$cmd\n");
|
add_info($tview,"$cmd\n");
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
if(length $stderr>1){
|
if(length $stderr>1){
|
add_colored_info(\$tview,"$stderr\n",'red');
|
add_colored_info($tview,"$stderr\n",'red');
|
}else {
|
}else {
|
add_info(\$tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
}
|
}
|
|
|
}else{
|
}else{
|
add_colored_info(\$tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red')
|
add_colored_info($tview,"Cannot find $bin executable binary file! make sure you have compiled the testbench successfully\n", 'red')
|
}
|
}
|
|
|
});
|
});
|
|
|
|
|
}
|
}
|
|
|
|
|
|
|
1;
|
1;
|
|
|
No newline at end of file
|
No newline at end of file
|