#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
use constant::boolean;
|
use constant::boolean;
|
use strict;
|
use strict;
|
use warnings;
|
use warnings;
|
|
|
use FindBin;
|
use FindBin;
|
use lib $FindBin::Bin;
|
use lib $FindBin::Bin;
|
|
|
use soc;
|
use soc;
|
|
|
|
|
use File::Path;
|
use File::Path;
|
use File::Find::Rule;
|
use File::Find::Rule;
|
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 List::MoreUtils qw( minmax );
|
use List::MoreUtils qw( minmax );
|
|
|
|
|
|
|
################
|
################
|
# Compile
|
# Compile
|
#################
|
#################
|
|
|
|
|
|
|
sub is_capital_sensitive()
|
sub is_capital_sensitive()
|
{
|
{
|
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 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);
|
|
|
|
|
if ($range[0] ne '*undefine*'){
|
if ($range[0] ne '*undefine*'){
|
my $content = join(",", @range);
|
my $content = join(",", @range);
|
my ($min, $max) = minmax @range;
|
my ($min, $max) = minmax @range;
|
if (length($portrange)!=0){
|
if (length($portrange)!=0){
|
my $range_hsb=gen_combobox_object($self,'compile_pin_range_hsb',$portname,$content,$max,undef,undef);
|
my $range_hsb=gen_combobox_object($self,'compile_pin_range_hsb',$portname,$content,$max,undef,undef);
|
$box->pack_start( $range_hsb, FALSE, FALSE, 0);
|
$box->pack_start( $range_hsb, FALSE, FALSE, 0);
|
$box->pack_start(gen_label_in_center(':'),, FALSE, FALSE, 0);
|
$box->pack_start(gen_label_in_center(':'),, FALSE, FALSE, 0);
|
}
|
}
|
|
|
my $range_lsb=gen_combobox_object($self,'compile_pin_range_lsb',$portname,$content,$min,undef,undef);
|
my $range_lsb=gen_combobox_object($self,'compile_pin_range_lsb',$portname,$content,$min,undef,undef);
|
$box->pack_start( $range_lsb, FALSE, FALSE, 0);
|
$box->pack_start( $range_lsb, FALSE, FALSE, 0);
|
|
|
}
|
}
|
return $box;
|
return $box;
|
|
|
}
|
}
|
|
|
|
|
sub read_top_v_file{
|
sub read_top_v_file{
|
my $top_v=shift;
|
my $top_v=shift;
|
my $board = soc->board_new();
|
my $board = soc->board_new();
|
my $vdb=read_verilog_file($top_v);
|
my $vdb=read_verilog_file($top_v);
|
my @modules=sort $vdb->get_modules($top_v);
|
my @modules=sort $vdb->get_modules($top_v);
|
my %Ptypes=get_ports_type($vdb,$modules[0]);
|
my %Ptypes=get_ports_type($vdb,$modules[0]);
|
my %Pranges=get_ports_rang($vdb,$modules[0]);
|
my %Pranges=get_ports_rang($vdb,$modules[0]);
|
foreach my $p (sort keys %Ptypes){
|
foreach my $p (sort keys %Ptypes){
|
my $Ptype=$Ptypes{$p};
|
my $Ptype=$Ptypes{$p};
|
my $Prange=$Pranges{$p};
|
my $Prange=$Pranges{$p};
|
my $type=($Ptype eq "input")? "Input" : ($Ptype eq "output")? 'Output' : 'Bidir';
|
my $type=($Ptype eq "input")? "Input" : ($Ptype eq "output")? 'Output' : 'Bidir';
|
if ( $Prange ne ''){
|
if ( $Prange ne ''){
|
my @r=split(":",$Prange);
|
my @r=split(":",$Prange);
|
my $a=($r[0]<$r[1])? $r[0] : $r[1];
|
my $a=($r[0]<$r[1])? $r[0] : $r[1];
|
my $b=($r[0]<$r[1])? $r[1] : $r[0];
|
my $b=($r[0]<$r[1])? $r[1] : $r[0];
|
for (my $i=$a; $i<=$b; $i++){
|
for (my $i=$a; $i<=$b; $i++){
|
$board->board_add_pin ($type,"$p\[$i\]");
|
$board->board_add_pin ($type,"$p\[$i\]");
|
|
|
}
|
}
|
}
|
}
|
else {$board->board_add_pin ($type,$p);}
|
else {$board->board_add_pin ($type,$p);}
|
}
|
}
|
return $board;
|
return $board;
|
}
|
}
|
|
|
|
|
|
|
|
|
sub gen_top_v{
|
sub gen_top_v{
|
my ($self,$board,$name,$top)=@_;
|
my ($self,$board,$name,$top)=@_;
|
|
|
my $top_v=get_license_header("Top.v");
|
my $top_v=get_license_header("Top.v");
|
#read port list
|
#read port list
|
my $vdb=read_verilog_file($top);
|
my $vdb=read_verilog_file($top);
|
my %port_type=get_ports_type($vdb,"${name}_top");
|
my %port_type=get_ports_type($vdb,"${name}_top");
|
my %port_range=get_ports_rang($vdb,"${name}_top");
|
my %port_range=get_ports_rang($vdb,"${name}_top");
|
|
|
|
|
my $io='';
|
my $io='';
|
my $io_def='';
|
my $io_def='';
|
my $io_assign='';
|
my $io_assign='';
|
my %board_io;
|
my %board_io;
|
my $first=1;
|
my $first=1;
|
foreach my $p (sort keys %port_type){
|
foreach my $p (sort keys %port_type){
|
my $porttype=$port_type{$p};
|
my $porttype=$port_type{$p};
|
my $portrange=$port_range{$p};
|
my $portrange=$port_range{$p};
|
my $assign_type = $self->object_get_attribute('compile_assign_type',$p);
|
my $assign_type = $self->object_get_attribute('compile_assign_type',$p);
|
my $assign_name = $self->object_get_attribute('compile_pin',$p);
|
my $assign_name = $self->object_get_attribute('compile_pin',$p);
|
my $range_hsb = $self->object_get_attribute('compile_pin_range_hsb',$p);
|
my $range_hsb = $self->object_get_attribute('compile_pin_range_hsb',$p);
|
my $range_lsb = $self->object_get_attribute('compile_pin_range_lsb',$p);
|
my $range_lsb = $self->object_get_attribute('compile_pin_range_lsb',$p);
|
my $assign="\t";
|
my $assign="\t";
|
if (defined $assign_name){
|
if (defined $assign_name){
|
if($assign_name eq '*VCC'){
|
if($assign_name eq '*VCC'){
|
$assign= (length($portrange)!=0)? '{32{1\'b1}}' : '1\'b1';
|
$assign= (length($portrange)!=0)? '{32{1\'b1}}' : '1\'b1';
|
} elsif ($assign_name eq '*GND'){
|
} elsif ($assign_name eq '*GND'){
|
$assign= (length($portrange)!=0)? '{32{1\'b0}}' : '1\'b0';
|
$assign= (length($portrange)!=0)? '{32{1\'b0}}' : '1\'b0';
|
}elsif ($assign_name eq '*NOCONNECT'){
|
}elsif ($assign_name eq '*NOCONNECT'){
|
$assign="\t";
|
$assign="\t";
|
|
|
}else{
|
}else{
|
|
|
$board_io{$assign_name}=$porttype;
|
$board_io{$assign_name}=$porttype;
|
|
|
|
|
my $range = (defined $range_hsb) ? "[$range_hsb : $range_lsb]" :
|
my $range = (defined $range_hsb) ? "[$range_hsb : $range_lsb]" :
|
(defined $range_lsb) ? "[ $range_lsb]" : " ";
|
(defined $range_lsb) ? "[ $range_lsb]" : " ";
|
my $l=(defined $assign_type)?
|
my $l=(defined $assign_type)?
|
($assign_type eq 'Direct') ? '' : '~' : '';
|
($assign_type eq 'Direct') ? '' : '~' : '';
|
$assign="$l $assign_name $range";
|
$assign="$l $assign_name $range";
|
|
|
|
|
}
|
}
|
}
|
}
|
$io_assign= ($first)? "$io_assign \t .$p($assign)":"$io_assign,\n \t .$p($assign)";
|
$io_assign= ($first)? "$io_assign \t .$p($assign)":"$io_assign,\n \t .$p($assign)";
|
$first=0;
|
$first=0;
|
}
|
}
|
$first=1;
|
$first=1;
|
foreach my $p (sort keys %board_io){
|
foreach my $p (sort keys %board_io){
|
$io=($first)? "\t$p" : "$io,\n\t$p";
|
$io=($first)? "\t$p" : "$io,\n\t$p";
|
my $dir=$board_io{$p};
|
my $dir=$board_io{$p};
|
my $range;
|
my $range;
|
my $type= ($dir eq 'input') ? 'Input' :
|
my $type= ($dir eq 'input') ? 'Input' :
|
($dir eq 'output')? 'Output' : 'Bidir';
|
($dir eq 'output')? 'Output' : 'Bidir';
|
my @r= $board->board_get_pin_range($type,$p);
|
my @r= $board->board_get_pin_range($type,$p);
|
if ($r[0] eq '*undefine*'){
|
if ($r[0] eq '*undefine*'){
|
$range="\t\t\t";
|
$range="\t\t\t";
|
} else {
|
} else {
|
my ($min, $max) = minmax @r;
|
my ($min, $max) = minmax @r;
|
$range="\t[$max : $min]\t";
|
$range="\t[$max : $min]\t";
|
}
|
}
|
$io_def = "$io_def \t $dir $range $p;\n";
|
$io_def = "$io_def \t $dir $range $p;\n";
|
$first=0;
|
$first=0;
|
|
|
}
|
}
|
$top_v="$top_v
|
$top_v="$top_v
|
module Top (
|
module Top (
|
$io
|
$io
|
);
|
);
|
$io_def
|
$io_def
|
|
|
${name}_top uut(
|
${name}_top uut(
|
$io_assign
|
$io_assign
|
);
|
);
|
|
|
|
|
endmodule
|
endmodule
|
";
|
";
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my $board_top_file= "$fpath/Top.v";
|
my $board_top_file= "$fpath/Top.v";
|
save_file($board_top_file,$top_v);
|
save_file($board_top_file,$top_v);
|
}
|
}
|
|
|
|
|
|
|
|
|
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');
|
|
|
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,Vivado,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 $vendor= ($old_compiler eq "QuartusII")? 'Altera' : 'Xilinx';
|
my $vendor= ($old_compiler eq "QuartusII")? 'Altera' : 'Xilinx';
|
|
|
#get the list of boards located in "boards/*" folder
|
#get the list of boards located in "boards/*" folder
|
my @dirs = grep {-d} glob("../boards/$vendor/*");
|
my @dirs = grep {-d} glob("../boards/$vendor/*");
|
my ($fpgas,$init);
|
my ($fpgas,$init);
|
foreach my $dir (@dirs) {
|
foreach my $dir (@dirs) {
|
my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
|
my ($name,$path,$suffix) = fileparse("$dir",qr"\..[^.]*$");
|
$init=$name;
|
$init=$name;
|
$fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
|
$fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
|
}
|
}
|
|
|
|
|
my $compiler_options =
|
my $compiler_options =
|
($old_compiler eq "QuartusII")? select_board ($self,$name,$top,$target_dir,$vendor):
|
($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 "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):
|
($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++){
|
|
|
my $temp=gen_label_in_center(" ");
|
my $temp=gen_label_in_center(" ");
|
$table->attach_defaults ($temp, 0, 1 , $i, $i+1);
|
$table->attach_defaults ($temp, 0, 1 , $i, $i+1);
|
}
|
}
|
$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',FALSE,1);
|
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" || $compiler_type eq "Vivado"){
|
if($compiler_type eq "QuartusII" || $compiler_type eq "Vivado"){
|
$vendor= ($compiler_type eq "QuartusII")? 'Altera' : 'Xilinx';
|
$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"\..[^.]*$");
|
#delete jtag_intfc.sh file
|
#delete jtag_intfc.sh file
|
unlink "${fpath}../sw/jtag_intfc.sh";
|
unlink "${fpath}../sw/jtag_intfc.sh";
|
#program_device.sh file
|
#program_device.sh file
|
unlink "${fpath}../program_device.sh";
|
unlink "${fpath}../program_device.sh";
|
}
|
}
|
|
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
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,$vendor);}
|
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,$vendor);}
|
else {get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);}
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
elsif($compiler_type eq "Modelsim"){
|
elsif($compiler_type eq "Modelsim"){
|
modelsim_compilation($self,$name,$top,$target_dir,$vendor);
|
modelsim_compilation($self,$name,$top,$target_dir,$vendor);
|
|
|
}else{#verilator
|
}else{#verilator
|
verilator_compilation_win($self,$name,$top,$target_dir,$vendor);
|
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 =
|
$compiler_options =
|
($new_board_name eq "QuartusII")? select_board ($self,$name,$top,$target_dir,"Altera"):
|
($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 "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):
|
($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;
|
|
|
});
|
});
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
sub select_board {
|
sub select_board {
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
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/$vendor/*");
|
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"\..[^.]*$");
|
|
|
$fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
|
$fpgas= (defined $fpgas)? "$fpgas,$name" : "$name";
|
$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 $compiler = ($vendor eq "Altera")? 'quartus' : 'vivado';
|
my $bin_name = "$compiler bin";
|
my $bin_name = "$compiler bin";
|
my $env = ($vendor eq "Altera")? "QUARTUS_BIN" : "VIVADO_BIN";
|
my $env = ($vendor eq "Altera")? "QUARTUS_BIN" : "VIVADO_BIN";
|
my $Fpga_bin= $ENV{$env};
|
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/$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_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',$bin_name);
|
|
|
$col=0;
|
$col=0;
|
$self->object_add_attribute('compile',$bin_name,$Fpga_bin) if (!defined $bin && defined $Fpga_bin);
|
$self->object_add_attribute('compile',$bin_name,$Fpga_bin) if (!defined $bin && defined $Fpga_bin);
|
$table->attach(gen_label_help("Path to $vendor/bin directory. You can set a default path as $env environment 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 $env=/home/alireza/$compiler/bin","$env:"),$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',$bin_name,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);
|
my $col=0;
|
my $col=0;
|
my $row=0;
|
my $row=0;
|
|
|
|
|
|
|
|
|
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 environment 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;
|
|
|
}
|
}
|
|
|
|
my $cpu_num;
|
sub select_parallel_process_num {
|
sub select_parallel_process_num {
|
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);
|
my $col=0;
|
my $col=0;
|
my $row=0;
|
my $row=0;
|
|
|
#get total number of processor in the system
|
#get total number of processor in the system
|
my $cmd = "nproc\n";
|
my $cmd = "nproc\n";
|
my $cpu_num=4;
|
if(!defined $cpu_num){
|
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){
|
#nproc command has failed. set default 4 paralel processor
|
#nproc command has failed. set default 4 paralel processor
|
|
|
}else {
|
}else {
|
my ($number ) = $stdout =~ /(\d+)/;
|
my ($number ) = $stdout =~ /(\d+)/;
|
if (defined $number ){
|
if (defined $number ){
|
$cpu_num =$number if ($number > 0 );
|
$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');
|
($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;
|
return $table;
|
}
|
}
|
|
|
sub select_parallel_thread_num {
|
sub select_parallel_thread_num {
|
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);
|
my $col=0;
|
my $col=0;
|
my $row=0;
|
my $row=0;
|
|
|
#get total number of processor in the system
|
#get total number of processor in the system
|
my $cmd = "nproc\n";
|
my $cmd = "nproc\n";
|
my $cpu_num=4;
|
if(!defined $cpu_num){
|
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){
|
#nproc command has failed. set default 4 paralel processor
|
#nproc command has failed. set default 4 paralel processor
|
|
|
}else {
|
}else {
|
my ($number ) = $stdout =~ /(\d+)/;
|
my ($number ) = $stdout =~ /(\d+)/;
|
if (defined $number ){
|
if (defined $number ){
|
$cpu_num =$number if ($number > 0 );
|
$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');
|
($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;
|
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');
|
$self->object_remove_attribute('compile_pin_range_hsb');
|
$self->object_remove_attribute('compile_pin_range_hsb');
|
$self->object_remove_attribute('compile_pin_range_lsb');
|
$self->object_remove_attribute('compile_pin_range_lsb');
|
}
|
}
|
|
|
|
|
|
|
sub add_new_fpga_board{
|
sub add_new_fpga_board{
|
|
|
my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
|
|
my $window = def_popwin_size(50,80,"Add New $vendor FPGA Board",'percent');
|
my $window = def_popwin_size(50,80,"Add New $vendor FPGA Board",'percent');
|
my $table = def_table(2, 2, FALSE);
|
my $table = def_table(2, 2, FALSE);
|
my $scrolled_win=add_widget_to_scrolled_win($table);
|
my $scrolled_win=add_widget_to_scrolled_win($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');
|
$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) if (defined $name);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2) if (defined $name);
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
$mtable->attach($next,8,9,9,10,'shrink','shrink',2,2);
|
|
|
|
|
my ($Twin,$tview)=create_txview();
|
my ($Twin,$tview)=create_txview();
|
|
|
|
|
my $widgets=
|
my $widgets=
|
($vendor eq 'Altera')? add_new_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor):
|
($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);
|
add_new_xilinx_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor,$tview);
|
|
|
|
|
|
|
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);
|
#$table->attach_defaults( $Twin,0,3,1,2);
|
#$table->attach_defaults( $Twin,0,3,1,2);
|
|
|
|
|
|
|
|
|
$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);
|
|
|
});
|
});
|
|
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
my $result = ($vendor eq 'Altera')?
|
my $result = ($vendor eq 'Altera')?
|
add_new_altera_fpga_board_files($self,$vendor):
|
add_new_altera_fpga_board_files($self,$vendor):
|
add_new_xilinx_fpga_board_files($self,$vendor);
|
add_new_xilinx_fpga_board_files($self,$vendor);
|
|
|
if(! defined $result ){
|
if(! defined $result ){
|
select_compiler($self,$name,$top,$target_dir,$end_func) if (defined $name);
|
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!");
|
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'){
|
if($vendor eq 'Altera'){
|
my $auto=def_image_button('icons/advance.png','Auto-fill');
|
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.");
|
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);
|
$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 $project_dir = get_project_dir();
|
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','board_confg_file');
|
my $qsf=$self->object_get_attribute('compile','board_confg_file');
|
if(!defined $qsf ){
|
if(!defined $qsf ){
|
add_colored_info ($tview,"Cannot detect device 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 name in qsf file
|
#search for device name in 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){
|
my @e=split /\s+/, $c;
|
my @e=split /\s+/, $c;
|
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_altera_fpga_board_widgets($self,$name,$top,$target_dir,$end_func,$vendor);
|
$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{
|
sub add_new_xilinx_fpga_board_widgets{
|
my ($self,$name,$top,$target_dir,$end_func,$vendor,$tview)=@_;
|
my ($self,$name,$top,$target_dir,$end_func,$vendor,$tview)=@_;
|
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 $help1="Your given FPGA Board name. Do not use any space in given name";
|
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 $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 $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 $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 $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 $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 $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
|
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
|
open_hw
|
connect_hw_server
|
connect_hw_server
|
open_hw_target
|
open_hw_target
|
get_hw_devices
|
get_hw_devices
|
It supposed to show the list of your hardware devices in your FPGA. Select the name represent your FPGA device
|
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";
|
my $repo ="$ENV{PRONOC_WORK}/toolchain/board_files";
|
|
|
|
|
$row++;
|
$row++;
|
|
|
my @info = (
|
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=>"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=>"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 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 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=>"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=>"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 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},
|
{ 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 %widgets;
|
my %rows;
|
my %rows;
|
foreach my $d (@info) {
|
foreach my $d (@info) {
|
$rows{$d->{param_name}} =$row;
|
$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');
|
($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 $icon = 'icons/advance.png';
|
my $search=def_image_button($icon,undef);
|
my $search=def_image_button($icon,undef);
|
my $search_board=def_image_button ($icon,undef);
|
my $search_board=def_image_button ($icon,undef);
|
my $search_dev=def_image_button ($icon,undef);
|
my $search_dev=def_image_button ($icon,undef);
|
my $search_chain=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,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_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_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);
|
$table->attach($search_chain,4,5,$rows{'fpga_board_order'},$rows{'fpga_board_order'}+1,'fill','shrink',2,2);
|
|
|
|
|
$search->signal_connect("clicked" => sub{
|
$search->signal_connect("clicked" => sub{
|
my $load= show_gif("icons/load.gif");
|
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->attach ($load,5, 6, $rows{'fpga_board_part'},$rows{'fpga_board_part'}+ 1,'shrink','shrink',0,0);
|
$table->show_all;
|
$table->show_all;
|
my $result= set_xilinx_board_from_repo($self,$tview);
|
my $result= set_xilinx_board_from_repo($self,$tview);
|
update_combo_entry_content($widgets{'fpga_board_part'}, $result);
|
update_combo_entry_content($widgets{'fpga_board_part'}, $result);
|
$load->destroy;
|
$load->destroy;
|
$table->show_all;
|
$table->show_all;
|
});
|
});
|
|
|
|
|
$search_board->signal_connect("clicked" => sub{
|
$search_board->signal_connect("clicked" => sub{
|
my $load= show_gif("icons/load.gif");
|
my $load= show_gif("icons/load.gif");
|
$table->attach ($load,5, 6, $rows{'fpga_part'},$rows{'fpga_part'}+1, 'shrink','shrink',0,0);
|
$table->attach ($load,5, 6, $rows{'fpga_part'},$rows{'fpga_part'}+1, 'shrink','shrink',0,0);
|
$table->show_all;
|
$table->show_all;
|
my $result= get_xilinx_board_part($self,$tview);
|
my $result= get_xilinx_board_part($self,$tview);
|
$widgets{'fpga_part'}->set_text($result);
|
$widgets{'fpga_part'}->set_text($result);
|
#print "result = $result\n";
|
#print "result = $result\n";
|
$load->destroy;
|
$load->destroy;
|
$table->show_all;
|
$table->show_all;
|
});
|
});
|
$search_dev->signal_connect("clicked" => sub{
|
$search_dev->signal_connect("clicked" => sub{
|
my $load= show_gif("icons/load.gif");
|
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->attach ($load,5, 6, $rows{'fpga_hw_device'},$rows{'fpga_hw_device'}+ 1,'shrink','shrink',0,0);
|
$table->show_all;
|
$table->show_all;
|
my $result= get_xilinx_device_names($self,$tview);
|
my $result= get_xilinx_device_names($self,$tview);
|
update_combo_entry_content($widgets{'fpga_hw_device'}, $result);
|
update_combo_entry_content($widgets{'fpga_hw_device'}, $result);
|
$load->destroy;
|
$load->destroy;
|
$table->show_all;
|
$table->show_all;
|
});
|
});
|
$search_chain->signal_connect("clicked" => sub{
|
$search_chain->signal_connect("clicked" => sub{
|
my $targets = show_all_xilinx_targets($self,$tview);
|
my $targets = show_all_xilinx_targets($self,$tview);
|
if(!defined $targets){
|
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");
|
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;
|
return;
|
}
|
}
|
|
|
my @lines=split(/\r?\n/,$targets);
|
my @lines=split(/\r?\n/,$targets);
|
my @list1;
|
my @list1;
|
my @list2;
|
my @list2;
|
foreach my $p (@lines){
|
foreach my $p (@lines){
|
$p =~ s/^\s+//;#left trim
|
$p =~ s/^\s+//;#left trim
|
my @words=split(/\s+/,$p);
|
my @words=split(/\s+/,$p);
|
push (@list1,$words[0]);
|
push (@list1,$words[0]);
|
push (@list2,$words[1]);
|
push (@list2,$words[1]);
|
}
|
}
|
my $hw = $self->object_get_attribute('compile','fpga_hw_device');
|
my $hw = $self->object_get_attribute('compile','fpga_hw_device');
|
if( !defined $hw){
|
if( !defined $hw){
|
add_colored_info($tview,"Please define the FPGA hardware device name first!\n",'red');
|
add_colored_info($tview,"Please define the FPGA hardware device name first!\n",'red');
|
return;
|
return;
|
}
|
}
|
my $pos = find_the_most_similar_position ($hw ,@list2);
|
my $pos = find_the_most_similar_position ($hw ,@list2);
|
add_info($tview,"$hw matched with target $list1[$pos] $list2[$pos] ");
|
add_info($tview,"$hw matched with target $list1[$pos] $list2[$pos] ");
|
$widgets{'fpga_board_order'}->set_value($list1[$pos]);
|
$widgets{'fpga_board_order'}->set_value($list1[$pos]);
|
});
|
});
|
|
|
return ($row, $col, $table);
|
return ($row, $col, $table);
|
}
|
}
|
|
|
|
|
|
|
sub set_xilinx_board_from_repo{
|
sub set_xilinx_board_from_repo{
|
my ($self,$tview)=@_;
|
my ($self,$tview)=@_;
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
my $result;
|
my $result;
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
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 $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";
|
my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl";
|
|
|
add_info($tview,"$command\n");
|
add_info($tview,"$command\n");
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
return if (!defined $stdout);
|
return if (!defined $stdout);
|
add_info($tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
my @boards=split(/\s+/,$stdout);
|
my @boards=split(/\s+/,$stdout);
|
my $r=0;
|
my $r=0;
|
foreach my $board (@boards){
|
foreach my $board (@boards){
|
my @pp=split(':',$board);
|
my @pp=split(':',$board);
|
if(scalar @pp == 4 && $pp[1] =~ /[a-zA-Z]+/) {
|
if(scalar @pp == 4 && $pp[1] =~ /[a-zA-Z]+/) {
|
$r=1;
|
$r=1;
|
$result= (!defined $result)? "$board" : $result.",$board";
|
$result= (!defined $result)? "$board" : $result.",$board";
|
}
|
}
|
}
|
}
|
add_colored_info($tview,"$stdout\n",'red') if($r==0);
|
add_colored_info($tview,"$stdout\n",'red') if($r==0);
|
return $result;
|
return $result;
|
}
|
}
|
|
|
|
|
sub get_xilinx_device_names{
|
sub get_xilinx_device_names{
|
my ($self,$tview)=@_;
|
my ($self,$tview)=@_;
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
my $result;
|
my $result;
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
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 $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";
|
my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl";
|
|
|
add_info($tview,"$command\n");
|
add_info($tview,"$command\n");
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
if (!defined $stdout){
|
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");
|
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;
|
return;
|
}
|
}
|
add_info($tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
my $devices = capture_string_between ('\n\*RESULT:',$stdout,"\n");
|
my $devices = capture_string_between ('\n\*RESULT:',$stdout,"\n");
|
my @D=split(/\s+/,$devices);
|
my @D=split(/\s+/,$devices);
|
return join ',', @D;
|
return join ',', @D;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
sub get_xilinx_board_part{
|
sub get_xilinx_board_part{
|
my ($self,$tview)=@_;
|
my ($self,$tview)=@_;
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
my $vivado =(defined $bin)? "${bin}/vivado" : "vivado";
|
my $result;
|
my $result;
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
my $board_part= $self->object_get_attribute('compile' ,'fpga_board_part');
|
my $board_part= $self->object_get_attribute('compile' ,'fpga_board_part');
|
if (!defined $board_part ){
|
if (!defined $board_part ){
|
add_colored_info($tview,"Please define the FPGA board part name first!\n",'red');
|
add_colored_info($tview,"Please define the FPGA board part name first!\n",'red');
|
return;
|
return;
|
}
|
}
|
|
|
my $tcl= get_project_dir()."/mpsoc/perl_gui/lib/tcl/vivado_get_part.tcl -tclargs $board_part $repo ";
|
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";
|
my $command = "cd $ENV{PRONOC_WORK}/tmp; $vivado -mode tcl -source $tcl";
|
|
|
add_info($tview,"$command\n");
|
add_info($tview,"$command\n");
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
my $stdout=run_cmd_textview_errors($command,$tview);
|
return if (!defined $stdout);
|
return if (!defined $stdout);
|
add_info($tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
return capture_string_between ('\n\*RESULT:',$stdout,"\n");
|
return capture_string_between ('\n\*RESULT:',$stdout,"\n");
|
}
|
}
|
|
|
|
|
|
|
sub add_new_altera_fpga_board_widgets{
|
sub add_new_altera_fpga_board_widgets{
|
my ($self,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
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 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/
|
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. Optionally 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 device location in jtag chain. Optionally 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 Board Name:", param_name=>'fpga_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=>'board_confg_file', 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=>'fpga_board_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 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 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 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 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 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},
|
{ 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,(gen_Hsep(),gen_label_in_center("FPGA Board JTAG Configuration"),gen_Hsep()));
|
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");
|
}
|
}
|
|
|
|
|
return ($row, $col, $table);
|
return ($row, $col, $table);
|
}
|
}
|
|
|
|
|
sub add_new_xilinx_fpga_board_files{
|
sub add_new_xilinx_fpga_board_files{
|
my ($self,$vendor)=@_;
|
my ($self,$vendor)=@_;
|
#check the board name
|
#check the board name
|
my $board_name=$self->object_get_attribute('compile','fpga_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 xdc file
|
#check xdc file
|
my $xdc=$self->object_get_attribute('compile','board_confg_file');
|
my $xdc=$self->object_get_attribute('compile','board_confg_file');
|
return "Please define the xdc file\n" if(!defined $xdc );
|
return "Please define the xdc file\n" if(!defined $xdc );
|
$xdc=add_project_dir_to_addr($xdc);
|
$xdc=add_project_dir_to_addr($xdc);
|
|
|
#check v file
|
#check v file
|
my $top=$self->object_get_attribute('compile','fpga_board_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 );
|
$top=add_project_dir_to_addr($top);
|
$top=add_project_dir_to_addr($top);
|
|
|
#check board part
|
#check board part
|
my $part=$self->object_get_attribute('compile','fpga_part');
|
my $part=$self->object_get_attribute('compile','fpga_part');
|
my $board_part=$self->object_get_attribute('compile','fpga_board_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 );
|
return "Please define at least one of FPGA board part or FPGA part names"if(!defined $part && !defined $board_part );
|
|
|
#make board directory
|
#make board directory
|
my $project_dir = get_project_dir();
|
my $project_dir = get_project_dir();
|
my $path="$project_dir/mpsoc/boards/$vendor/$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);
|
copy( $xdc,"$path/$board_name.xdc");
|
copy( $xdc,"$path/$board_name.xdc");
|
copy($top,"$path/$board_name.v");
|
copy($top,"$path/$board_name.v");
|
|
|
|
|
|
|
my $a=$self->object_get_attribute('compile','fpga_board_order');
|
my $a=$self->object_get_attribute('compile','fpga_board_order');
|
my $jtag_intfc="#!/bin/bash
|
my $jtag_intfc="#!/bin/bash
|
JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_xilinx_xsct -a $a -b 36\"
|
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
|
#it works only for 32-bit jtag data width for 64 pass -b 68
|
";
|
";
|
save_file ("$path/jtag_intfc.sh",$jtag_intfc);
|
save_file ("$path/jtag_intfc.sh",$jtag_intfc);
|
|
|
|
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $bin = $self->object_get_attribute('compile',"vivado bin");
|
my $hw_dev=$self->object_get_attribute('compile',"fpga_hw_device");
|
my $hw_dev=$self->object_get_attribute('compile',"fpga_hw_device");
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
my $repo= $self->object_get_attribute('compile','fpga_board_repo');
|
|
|
|
|
my $tcl="proc set_project_properties { } {\n";
|
my $tcl="proc set_project_properties { } {\n";
|
if(-d $repo){
|
if(-d $repo){
|
$tcl=$tcl."\tset_property \"board_part_repo_paths\" [list \"$repo\"] [current_project]\n";
|
$tcl=$tcl."\tset_property \"board_part_repo_paths\" [list \"$repo\"] [current_project]\n";
|
}else {
|
}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 \"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 \"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 \"board_part\" \"$board_part\" [current_project]\n" if(defined $board_part);
|
$tcl=$tcl."\tset_property \"default_lib\" \"xil_defaultlib\" [current_project]\n}\n";
|
$tcl=$tcl."\tset_property \"default_lib\" \"xil_defaultlib\" [current_project]\n}\n";
|
|
|
|
|
|
|
if (defined $hw_dev){
|
if (defined $hw_dev){
|
$tcl=$tcl."\n
|
$tcl=$tcl."\n
|
proc program_board {bit_file} {
|
proc program_board {bit_file} {
|
open_hw
|
open_hw
|
connect_hw_server
|
connect_hw_server
|
open_hw_target
|
open_hw_target
|
set_property PROGRAM.FILE \$bit_file [get_hw_devices $hw_dev]
|
set_property PROGRAM.FILE \$bit_file [get_hw_devices $hw_dev]
|
program_hw_devices [get_hw_devices $hw_dev]
|
program_hw_devices [get_hw_devices $hw_dev]
|
refresh_hw_device [get_hw_devices $hw_dev]
|
refresh_hw_device [get_hw_devices $hw_dev]
|
}
|
}
|
";
|
";
|
}
|
}
|
save_file ("$path/board_property.tcl",$tcl);
|
save_file ("$path/board_property.tcl",$tcl);
|
|
|
|
|
$self->object_add_attribute('compile','board',$board_name);
|
$self->object_add_attribute('compile','board',$board_name);
|
return undef;
|
return undef;
|
|
|
|
|
}
|
}
|
|
|
|
|
sub add_new_altera_fpga_board_files{
|
sub add_new_altera_fpga_board_files{
|
my ($self,$vendor)=@_;
|
my ($self,$vendor)=@_;
|
|
|
#check the board name
|
#check the board name
|
my $board_name=$self->object_get_attribute('compile','fpga_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','board_confg_file');
|
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','fpga_board_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 );
|
return "Please define the PID\n" if(length($pid) ==0 );
|
return "Please define the PID\n" if(length($pid) ==0 );
|
|
|
#check Hardware name
|
#check Hardware name
|
my $hw=$self->object_get_attribute('compile','quartus_hardware');
|
my $hw=$self->object_get_attribute('compile','quartus_hardware');
|
return "Please define the Hardware Name\n" if(! defined $hw );
|
return "Please define the Hardware Name\n" if(! defined $hw );
|
return "Please define the Hardware Name\n" if(length($hw) ==0 );
|
return "Please define the Hardware Name\n" if(length($hw) ==0 );
|
|
|
|
|
#check Device name name
|
#check Device name name
|
my $dw=$self->object_get_attribute('compile','quartus_device');
|
my $dw=$self->object_get_attribute('compile','quartus_device');
|
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 $project_dir = get_project_dir();
|
my $project_dir = get_project_dir();
|
my $path="$project_dir/mpsoc/boards/$vendor/$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);
|
$top=add_project_dir_to_addr($top);
|
$top=add_project_dir_to_addr($top);
|
open my $file, "<", $qsf or return "Error Could not open $qsf file in read mode!";
|
open my $file, "<", $qsf or return "Error Could not open $qsf file in read mode!";
|
open my $newqsf, ">", "$path/$board_name.qsf" or return "Error Could not create $path/$board_name.qsf file in write mode!";
|
open my $newqsf, ">", "$path/$board_name.qsf" or return "Error Could not create $path/$board_name.qsf file in write mode!";
|
|
|
#remove the lines contain following strings
|
#remove the lines contain following strings
|
my @p=("TOP_LEVEL_ENTITY","VERILOG_FILE","SYSTEMVERILOG_FILE","VHDL_FILE","AHDL_FILE","PROJECT_OUTPUT_DIRECTORY" );
|
my @p=("TOP_LEVEL_ENTITY","VERILOG_FILE","SYSTEMVERILOG_FILE","VHDL_FILE","AHDL_FILE","PROJECT_OUTPUT_DIRECTORY" );
|
while (my $line = <$file>){
|
while (my $line = <$file>){
|
if ($line =~ /\Q$p[0]\E/ || $line =~ /\Q$p[1]\E/ || $line =~ /\Q$p[2]\E/ || $line =~ /\Q$p[3]\E/ || $line =~ /\Q$p[4]\E/){#dont copy the line contain TOP_LEVEL_ENTITY
|
if ($line =~ /\Q$p[0]\E/ || $line =~ /\Q$p[1]\E/ || $line =~ /\Q$p[2]\E/ || $line =~ /\Q$p[3]\E/ || $line =~ /\Q$p[4]\E/){#dont copy the line contain TOP_LEVEL_ENTITY
|
|
|
}
|
}
|
|
|
else{
|
else{
|
print $newqsf $line;
|
print $newqsf $line;
|
}
|
}
|
|
|
}
|
}
|
print $newqsf "\nset_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files\n";
|
print $newqsf "\nset_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files\n";
|
|
|
close $newqsf;
|
close $newqsf;
|
close $file;
|
close $file;
|
copy($top,"$path/$board_name.v");
|
copy($top,"$path/$board_name.v");
|
|
|
#generate jtag_intfc.sh
|
#generate jtag_intfc.sh
|
open $file, ">", "$path/jtag_intfc.sh" or return "Error: Could not create $path/jtag_intfc.sh file in write mode!";
|
open $file, ">", "$path/jtag_intfc.sh" or return "Error: Could not create $path/jtag_intfc.sh file in write mode!";
|
my $jtag;
|
my $jtag;
|
if($pid eq 6001 || $pid eq 6002 || $pid eq 6003){
|
if($pid eq 6001 || $pid eq 6002 || $pid eq 6003){
|
$jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_libusb -a \$PRODUCT_ID\"";
|
$jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_libusb -a \$PRODUCT_ID\"";
|
|
|
}else{
|
}else{
|
$jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_quartus_stp -a \$HARDWARE_NAME -b \$DEVICE_NAME\"";
|
$jtag="JTAG_INTFC=\"\$PRONOC_WORK/toolchain/bin/jtag_quartus_stp -a \$HARDWARE_NAME -b \$DEVICE_NAME\"";
|
|
|
}
|
}
|
print $file "#!/bin/bash
|
print $file "#!/bin/bash
|
|
|
PRODUCT_ID=\"0x$pid\"
|
PRODUCT_ID=\"0x$pid\"
|
HARDWARE_NAME=\'$hw *\'
|
HARDWARE_NAME=\'$hw *\'
|
DEVICE_NAME=\"\@$dw*\"
|
DEVICE_NAME=\"\@$dw*\"
|
|
|
$jtag
|
$jtag
|
|
|
";
|
";
|
close $file;
|
close $file;
|
|
|
|
|
#generate program_device.sh
|
#generate program_device.sh
|
open $file, ">", "$path/program_device.sh" or return "Error: Could not create $path/program_device.sh file in write mode!";
|
open $file, ">", "$path/program_device.sh" or return "Error: Could not create $path/program_device.sh file in write mode!";
|
|
|
|
|
print $file "#!/bin/bash
|
print $file "#!/bin/bash
|
|
|
#usage:
|
#usage:
|
# bash program_device.sh programming_file.sof
|
# bash program_device.sh programming_file.sof
|
|
|
#programming file
|
#programming file
|
#given as an argument: \$1
|
#given as an argument: \$1
|
|
|
#Programming mode
|
#Programming mode
|
PROG_MODE=jtag
|
PROG_MODE=jtag
|
|
|
#cable name. Connect the board to ur PC and then run jtagconfig in terminal to find the cable name
|
#cable name. Connect the board to ur PC and then run jtagconfig in terminal to find the cable name
|
NAME=\"$hw\"
|
NAME=\"$hw\"
|
|
|
#device name
|
#device name
|
DEVICE=\@$dw".'
|
DEVICE=\@$dw".'
|
|
|
|
|
#programming command
|
#programming command
|
if [ -n "${QUARTUS_BIN+set}" ]; then
|
if [ -n "${QUARTUS_BIN+set}" ]; then
|
$QUARTUS_BIN/quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}"
|
$QUARTUS_BIN/quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}"
|
else
|
else
|
quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}"
|
quartus_pgm -m $PROG_MODE -c "$NAME" -o "p;${1}${DEVICE}"
|
fi
|
fi
|
';
|
';
|
|
|
close $file;
|
close $file;
|
$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,$vendor)=@_;
|
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 = add_widget_to_scrolled_win($table);
|
my $scrolled_win = add_widget_to_scrolled_win($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/$vendor/$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/$vendor/$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/$vendor/$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/$vendor/$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!",'error');
|
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);
|
|
|
# Write object file
|
# Write object file
|
#open(FILE, ">lib/soc/tttttttt") || die "Can not open: $!";
|
#open(FILE, ">lib/soc/tttttttt") || die "Can not open: $!";
|
#print FILE Data::Dumper->Dump([\%$board],['board']);
|
#print FILE Data::Dumper->Dump([\%$board],['board']);
|
#close(FILE) || die "Error closing file: $!";
|
#close(FILE) || die "Error closing file: $!";
|
|
|
my @dirs = ('Input', 'Bidir', 'Output');
|
my @dirs = ('Input', 'Bidir', 'Output');
|
my %models;
|
my %models;
|
foreach my $p (@dirs){
|
foreach my $p (@dirs){
|
my %pins=$board->board_get_pin($p);
|
my %pins=$board->board_get_pin($p);
|
$models{$p}=gen_combo_model(\%pins);
|
$models{$p}=gen_combo_model(\%pins);
|
|
|
}
|
}
|
|
|
my $row=0;
|
my $row=0;
|
my $col=0;
|
my $col=0;
|
my @labels= ('Port Direction','Port Range ','Port name ','Assignment 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 (@labels){
|
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++
|
}
|
}
|
$row++;
|
$row++;
|
|
|
|
|
#read port list
|
#read port list
|
my $vdb=read_verilog_file($top);
|
my $vdb=read_verilog_file($top);
|
my %port_type=get_ports_type($vdb,"${name}_top");
|
my %port_type=get_ports_type($vdb,"${name}_top");
|
my %port_range=get_ports_rang($vdb,"${name}_top");
|
my %port_range=get_ports_rang($vdb,"${name}_top");
|
my %param = $vdb->get_modules_parameters("${name}_top");
|
my %param = $vdb->get_modules_parameters("${name}_top");
|
|
|
foreach my $p (sort keys %port_type){
|
foreach my $p (sort keys %port_type){
|
my $porttype=$port_type{$p};
|
my $porttype=$port_type{$p};
|
my $portrange=$port_range{$p};
|
my $portrange=$port_range{$p};
|
|
|
if (length($portrange)!=0){
|
if (length($portrange)!=0){
|
#replace parameter with their values
|
#replace parameter with their values
|
my @a= split (/\b/,$portrange);
|
my @a= split (/\b/,$portrange);
|
|
|
foreach my $l (@a){
|
foreach my $l (@a){
|
my $value=$param{$l};
|
my $value=$param{$l};
|
if(defined $value){
|
if(defined $value){
|
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);
|
my($s1,$s2)=split (":",$portrange);
|
{
|
{
|
no warnings 'numeric';
|
no warnings 'numeric';
|
$s1 = eval $s1;
|
$s1 = eval $s1;
|
$s2 = eval $s2;
|
$s2 = eval $s2;
|
}
|
}
|
$portrange = "[ $portrange ]" ;
|
$portrange = "[ $portrange ]" ;
|
if(defined $s1 && defined $s2 ){
|
if(defined $s1 && defined $s2 ){
|
$portrange = "" if($s1 eq 0 && $s2 eq 0); #the upper and lower range are equal zero so remove it
|
$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");
|
|
|
$table->attach($label1, 0,1, $row, $row+1,'fill','shrink',2,2);
|
$table->attach($label1, 0,1, $row, $row+1,'fill','shrink',2,2);
|
$table->attach($label2, 1,2, $row, $row+1,'fill','shrink',2,2);
|
$table->attach($label2, 1,2, $row, $row+1,'fill','shrink',2,2);
|
$table->attach($label3, 2,3, $row, $row+1,'fill','shrink',2,2);
|
$table->attach($label3, 2,3, $row, $row+1,'fill','shrink',2,2);
|
|
|
my $assign_type= "Direct,Negate(~)";
|
my $assign_type= "Direct,Negate(~)";
|
if ($porttype eq 'input') {
|
if ($porttype eq 'input') {
|
my $assign_combo=gen_combobox_object($self,'compile_assign_type',$p,$assign_type,'Direct',undef,undef);
|
my $assign_combo=gen_combobox_object($self,'compile_assign_type',$p,$assign_type,'Direct',undef,undef);
|
$table->attach( $assign_combo, 3,4, $row, $row+1,'fill','shrink',2,2);
|
$table->attach( $assign_combo, 3,4, $row, $row+1,'fill','shrink',2,2);
|
}
|
}
|
|
|
my $type= ($porttype eq 'input') ? 'Input' :
|
my $type= ($porttype eq 'input') ? 'Input' :
|
($porttype eq 'output')? 'Output' : 'Bidir';
|
($porttype eq 'output')? 'Output' : 'Bidir';
|
|
|
my $combo= gen_tree_combo($models{$type});
|
my $combo= gen_tree_combo($models{$type});
|
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 = 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);
|
$box=get_range ($board,$self,$type,$text,$portrange,$p);
|
$box=get_range ($board,$self,$type,$text,$portrange,$p);
|
$table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
|
$table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
|
}
|
}
|
|
|
|
|
$combo->signal_connect("changed" => sub{
|
$combo->signal_connect("changed" => sub{
|
|
|
#get and saved new value
|
#get and saved new value
|
my $treeiter= $combo->get_active_iter();
|
my $treeiter= $combo->get_active_iter();
|
my $text = $models{$type}->get_value($treeiter, 0);
|
my $text = $models{$type}->get_value($treeiter, 0);
|
$self->object_add_attribute('compile_pin',$p,$text);
|
$self->object_add_attribute('compile_pin',$p,$text);
|
#get and saved value position in model
|
#get and saved value position in model
|
my $treepath = $models{$type}->get_path ($treeiter);
|
my $treepath = $models{$type}->get_path ($treeiter);
|
my @indices= $treepath->get_indices();
|
my @indices= $treepath->get_indices();
|
$self->object_add_attribute('compile_pin_pos',$p,\@indices);
|
$self->object_add_attribute('compile_pin_pos',$p,\@indices);
|
#update borad port range
|
#update borad port range
|
$box->destroy if(defined $box);
|
$box->destroy if(defined $box);
|
$box=get_range ($board,$self,$type,$text,$portrange,$p);
|
$box=get_range ($board,$self,$type,$text,$portrange,$p);
|
$table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
|
$table->attach($box, 5,6, $loc, $loc+1,'fill','shrink',2,2);
|
$table->show_all;
|
$table->show_all;
|
|
|
});
|
});
|
|
|
$table->attach($combo, 4,5, $row, $row+1,'fill','shrink',2,2);
|
$table->attach($combo, 4,5, $row, $row+1,'fill','shrink',2,2);
|
|
|
$row++;
|
$row++;
|
|
|
}
|
}
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
fpga_compilation($self,$board,$name,$top,$target_dir,$end_func,$vendor);
|
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,$vendor);
|
select_compiler($self,$name,$top,$target_dir,$end_func,$vendor);
|
|
|
});
|
});
|
|
|
|
|
$window->add ($mtable);
|
$window->add ($mtable);
|
$window->show_all();
|
$window->show_all();
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
sub fpga_compilation{
|
sub fpga_compilation{
|
my ($self,$board,$name,$top,$target_dir,$end_func,$vendor)=@_;
|
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');
|
|
|
|
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my ($fname,$fpath,$fsuffix) = fileparse("$top",qr"\..[^.]*$");
|
my $board_top_file ="${fpath}Top.v";
|
my $board_top_file ="${fpath}Top.v";
|
unless (-e $board_top_file ){
|
unless (-e $board_top_file ){
|
gen_top_v($self,$board,$name,$top) ;
|
gen_top_v($self,$board,$name,$top) ;
|
}
|
}
|
|
|
my ($app,$table,$tview,$window) = software_main($fpath,'Top.v');
|
my ($app,$table,$tview,$window) = software_main($fpath,'Top.v');
|
$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,6, 7, 1,2,'shrink','shrink',2,2);
|
$table->attach ($run,6, 7, 1,2,'shrink','shrink',2,2);
|
$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 $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");
|
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");
|
if ($response eq 'yes') {
|
if ($response eq 'yes') {
|
gen_top_v($self,$board,$name,$top);
|
gen_top_v($self,$board,$name,$top);
|
$app->refresh_source("$board_top_file");
|
$app->refresh_source("$board_top_file");
|
}
|
}
|
});
|
});
|
|
|
|
|
|
|
$back-> signal_connect("clicked" => sub{
|
$back-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);
|
get_pin_assignment($self,$name,$top,$target_dir,$end_func,$vendor);
|
|
|
});
|
});
|
|
|
|
|
#compile
|
#compile
|
$run-> signal_connect("clicked" => sub{
|
$run-> signal_connect("clicked" => sub{
|
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->ask_to_save_changes();
|
$app->ask_to_save_changes();
|
|
|
quartus_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Altera');
|
quartus_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Altera');
|
xilinx_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Xilinx');
|
xilinx_run_compile ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor) if($vendor eq 'Xilinx');
|
|
|
$load->destroy;
|
$load->destroy;
|
|
|
});
|
});
|
|
|
|
|
#Programe the board
|
#Programe the board
|
$prog-> signal_connect("clicked" => sub{
|
$prog-> signal_connect("clicked" => sub{
|
quartus_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Altera');
|
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');
|
vivado_program_the_board($self,$tview,$target_dir,$name,$vendor) if($vendor eq 'Xilinx');
|
});
|
});
|
|
|
}
|
}
|
|
|
sub vivado_program_the_board {
|
sub vivado_program_the_board {
|
my ($self,$tview,$target_dir,$name,$vendor) =@_;
|
my ($self,$tview,$target_dir,$name,$vendor) =@_;
|
|
|
my $bit_file="$target_dir/Vivado/xilinx_compile/${name}.runs/impl_1/Top.bit";
|
my $bit_file="$target_dir/Vivado/xilinx_compile/${name}.runs/impl_1/Top.bit";
|
|
|
|
|
|
|
unless (-f "$target_dir/Vivado/program_board.tcl"){
|
unless (-f "$target_dir/Vivado/program_board.tcl"){
|
#create tcl file
|
#create tcl file
|
my $xpr = "\$tcl_path/xilinx_compile/${name}.xpr";
|
my $xpr = "\$tcl_path/xilinx_compile/${name}.xpr";
|
my $tcl="
|
my $tcl="
|
#Get tcl shell path relative to current script
|
#Get tcl shell path relative to current script
|
set tcl_path [file dirname [info script]]
|
set tcl_path [file dirname [info script]]
|
|
|
set projectName $name
|
set projectName $name
|
|
|
source \"\$tcl_path/board_property.tcl\"
|
source \"\$tcl_path/board_property.tcl\"
|
set projectXpr \"$xpr\"
|
set projectXpr \"$xpr\"
|
#Open project
|
#Open project
|
open_project \$projectXpr
|
open_project \$projectXpr
|
program_board \"\$tcl_path/xilinx_compile/${name}.runs/impl_1/Top.bit\"
|
program_board \"\$tcl_path/xilinx_compile/${name}.runs/impl_1/Top.bit\"
|
close_project
|
close_project
|
exit
|
exit
|
|
|
";
|
";
|
save_file ("$target_dir/Vivado/program_board.tcl",$tcl);
|
save_file ("$target_dir/Vivado/program_board.tcl",$tcl);
|
add_info($tview,"File $target_dir/Vivado/program_board.tcl is created\n");
|
add_info($tview,"File $target_dir/Vivado/program_board.tcl is created\n");
|
}
|
}
|
|
|
#check bit file existance
|
#check bit file existance
|
unless (-f $bit_file){
|
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');
|
add_colored_info($tview,"Could not find $bit_file. Click on project Compile button first and make sure it runs successfully.",'red');
|
return
|
return
|
}
|
}
|
|
|
|
|
#run vivado using program_board.tcl
|
#run vivado using program_board.tcl
|
my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/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);
|
add_colored_info($tview,"Board is programmed successfully!\n",'blue') if($error==0);
|
|
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
sub quartus_program_the_board{
|
sub quartus_program_the_board{
|
my ($self,$tview,$target_dir,$name,$vendor)=@_;
|
my ($self,$tview,$target_dir,$name,$vendor)=@_;
|
my $error = 0;
|
my $error = 0;
|
my $sof_file="$target_dir/Quartus/output_files/${name}.sof";
|
my $sof_file="$target_dir/Quartus/output_files/${name}.sof";
|
my $bash_file="$target_dir/program_device.sh";
|
my $bash_file="$target_dir/program_device.sh";
|
|
|
add_info($tview,"Program the board using Quartus_pgm and $sof_file file\n");
|
add_info($tview,"Program the board using Quartus_pgm and $sof_file file\n");
|
#check if the programming file exists
|
#check if the programming file exists
|
unless (-f $sof_file) {
|
unless (-f $sof_file) {
|
add_colored_info($tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red');
|
add_colored_info($tview,"\tThe $sof_file does not exists! Make sure you have compiled the code successfully.\n", 'red');
|
$error=1;
|
$error=1;
|
}
|
}
|
#check if the program_device.sh file exists
|
#check if the program_device.sh file exists
|
unless (-f $bash_file) {
|
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');
|
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;
|
$error=1;
|
}
|
}
|
return if($error);
|
return if($error);
|
my $command = "bash $bash_file $sof_file";
|
my $command = "bash $bash_file $sof_file";
|
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,"Board was not programmed successfully!\n",'red');
|
add_colored_info($tview,"Board was not programmed 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,"Board was not programmed successfully!\n",'red');
|
add_colored_info($tview,"Board was not programmed successfully!\n",'red');
|
}else{
|
}else{
|
add_info($tview,"$stdout\n");
|
add_info($tview,"$stdout\n");
|
add_colored_info($tview,"Board is programmed successfully!\n",'blue');
|
add_colored_info($tview,"Board is programmed successfully!\n",'blue');
|
}
|
}
|
|
|
}
|
}
|
}
|
}
|
|
|
|
|
sub quartus_run_compile{
|
sub quartus_run_compile{
|
my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_;
|
my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_;
|
|
|
my $error = 0;
|
my $error = 0;
|
add_info($tview,"CREATE: start creating Quartus project in $target_dir/Quartus folder\n");
|
add_info($tview,"CREATE: start creating Quartus project in $target_dir/Quartus folder\n");
|
|
|
mkpath("$target_dir/Quartus",1,01777);
|
mkpath("$target_dir/Quartus",1,01777);
|
|
|
#get list of source file
|
#get list of source file
|
add_info($tview," Read the list of all source files $target_dir/src_verilog\n");
|
add_info($tview," Read the list of all source files $target_dir/src_verilog\n");
|
my @files = File::Find::Rule->file()
|
my @files = File::Find::Rule->file()
|
->name( '*.v','*.V','*.sv' )
|
->name( '*.v','*.V','*.sv' )
|
->in( "$target_dir/src_verilog" );
|
->in( "$target_dir/src_verilog" );
|
|
|
#make sure source files have key word 'module'
|
#make sure source files have key word 'module'
|
my @sources;
|
my @sources;
|
foreach my $p (@files){
|
foreach my $p (@files){
|
push (@sources,$p) if(check_file_has_string($p,'endpackage'));
|
push (@sources,$p) if(check_file_has_string($p,'endpackage'));
|
}
|
}
|
foreach my $p (@files){
|
foreach my $p (@files){
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
}
|
}
|
my $files = join ("\n",@sources);
|
my $files = join ("\n",@sources);
|
add_info($tview,"$files\n");
|
add_info($tview,"$files\n");
|
|
|
#creat project qsf file
|
#creat project qsf file
|
my $qsf_file="$target_dir/Quartus/${name}.qsf";
|
my $qsf_file="$target_dir/Quartus/${name}.qsf";
|
save_file ($qsf_file,"# Generated using ProNoC\n");
|
save_file ($qsf_file,"# Generated using ProNoC\n");
|
|
|
#append global assignets to qsf file
|
#append global assignets to qsf file
|
my $board_name=$self->object_get_attribute('compile','board');
|
my $board_name=$self->object_get_attribute('compile','board');
|
my @qsfs = glob("../boards/$vendor/$board_name/*.qsf");
|
my @qsfs = glob("../boards/$vendor/$board_name/*.qsf");
|
if(!defined $qsfs[0]){
|
if(!defined $qsfs[0]){
|
message_dialog("Error: ../boards/$vendor/$board_name folder does not contain the qsf file.!",'error');
|
message_dialog("Error: ../boards/$vendor/$board_name folder does not contain the qsf file.!",'error');
|
$window->destroy;
|
$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;
|
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;
|
$paths{$path}=1;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach my $p (sort keys %paths){
|
foreach my $p (sort keys %paths){
|
$s="$s set_global_assignment -name SEARCH_PATH $p\n";
|
$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');
|
my @qfiles = ("quartus_map","quartus_fit","quartus_asm","quartus_sta");
|
my @qfiles = ("quartus_map","quartus_fit","quartus_asm","quartus_sta");
|
foreach my $f (@qfiles){
|
foreach my $f (@qfiles){
|
unless(-f "$Quartus_bin/$f" ){
|
unless(-f "$Quartus_bin/$f" ){
|
$error=1;
|
$error=1;
|
add_colored_info($tview, "$Quartus_bin/$f No such file or directory\n",'red');
|
add_colored_info($tview, "$Quartus_bin/$f No such file or directory\n",'red');
|
last;
|
last;
|
}
|
}
|
|
|
}
|
}
|
|
|
my $run_sh = "#!/bin/bash
|
my $run_sh = "#!/bin/bash
|
$Quartus_bin/quartus_map --64bit $name --read_settings_files=on
|
$Quartus_bin/quartus_map --64bit $name --read_settings_files=on
|
$Quartus_bin/quartus_fit --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_asm --64bit $name --read_settings_files=on
|
$Quartus_bin/quartus_sta --64bit $name
|
$Quartus_bin/quartus_sta --64bit $name
|
";
|
";
|
|
|
save_file("$target_dir/Quartus/run.sh", $run_sh);
|
save_file("$target_dir/Quartus/run.sh", $run_sh);
|
|
|
add_info($tview, "Start Quartus compilation.....\n");
|
add_info($tview, "Start Quartus compilation.....\n");
|
my @compilation_command =(
|
my @compilation_command =(
|
"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/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_map --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ",
|
"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/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_fit --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ",
|
"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/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_asm --64bit $name --read_settings_files=on; echo \$? > status; sleep 1' ",
|
"cd \"$target_dir/Quartus\" \n xterm -e bash -c '$Quartus_bin/quartus_sta --64bit $name; echo \$? > status; sleep 1 ' ");
|
"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){
|
last if($error);
|
last if($error);
|
add_info($tview,"$cmd\n");
|
add_info($tview,"$cmd\n");
|
unlink "$target_dir/Quartus/status";
|
unlink "$target_dir/Quartus/status";
|
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($exit){
|
if($exit){
|
add_colored_info($tview, "$stdout\n",'red') if(defined $stdout);
|
add_colored_info($tview, "$stdout\n",'red') if(defined $stdout);
|
add_colored_info($tview, "$stderr\n",'red') if(defined $stderr);
|
add_colored_info($tview, "$stderr\n",'red') if(defined $stderr);
|
$error=1;
|
$error=1;
|
last;
|
last;
|
}
|
}
|
|
|
open(my $fh, "<$target_dir/Quartus/status") || die "Can not open: $!";
|
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,$stderr)=run_cmd_in_back_ground_get_stdout("cd \"$target_dir/Quartus/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,"$stderr\n",'red') if(defined $stderr);
|
add_colored_info($tview,"$stderr\n",'red') if(defined $stderr);
|
add_colored_info($tview,"$stdout\n",'red');
|
add_colored_info($tview,"$stdout\n",'red');
|
$error=1;
|
$error=1;
|
last;
|
last;
|
}
|
}
|
}
|
}
|
add_colored_info($tview,"Quartus compilation failed !\n",'red') if($error==1);
|
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);
|
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');
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
sub xilinx_run_compile{
|
sub xilinx_run_compile{
|
my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_;
|
my ($self,$app,$tview,$target_dir,$name,$window,$end_func,$vendor)=@_;
|
|
|
add_info($tview,"CREATE: start creating Vivado project in $target_dir/Vivado\n");
|
add_info($tview,"CREATE: start creating Vivado project in $target_dir/Vivado\n");
|
#get list of source file
|
#get list of source file
|
add_info($tview," Read the list of all source files $target_dir/src_verilog\n");
|
add_info($tview," Read the list of all source files $target_dir/src_verilog\n");
|
my @files = File::Find::Rule->file()
|
my @files = File::Find::Rule->file()
|
->name( '*.v','*.V','*.sv' )
|
->name( '*.v','*.V','*.sv' )
|
->in( "$target_dir/src_verilog" );
|
->in( "$target_dir/src_verilog" );
|
|
|
#make sure source files have key word 'module'
|
#make sure source files have key word 'module'
|
my @sources;
|
my @sources;
|
foreach my $p (@files){
|
foreach my $p (@files){
|
push (@sources,$p) if(check_file_has_string($p,'endpackage'));
|
push (@sources,$p) if(check_file_has_string($p,'endpackage'));
|
}
|
}
|
foreach my $p (@files){
|
foreach my $p (@files){
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
push (@sources,$p) if(check_file_has_string($p,'module'));
|
}
|
}
|
|
|
my %paths;
|
my %paths;
|
foreach my $p (@files){
|
foreach my $p (@files){
|
my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
|
my ($name,$path,$suffix) = fileparse("$p",qr"\..[^.]*$");
|
#print "$path\n";
|
#print "$path\n";
|
my $remove="$target_dir/";
|
my $remove="$target_dir/";
|
$path =~ s/$remove//;
|
$path =~ s/$remove//;
|
$paths{$path}=1;
|
$paths{$path}=1;
|
}
|
}
|
|
|
|
|
|
|
|
|
my $incdir="set include_dir_list [list";
|
my $incdir="set include_dir_list [list";
|
foreach my $p (sort keys %paths){
|
foreach my $p (sort keys %paths){
|
$incdir.=" \$Dir/$p";
|
$incdir.=" \$Dir/$p";
|
}
|
}
|
$incdir.="]";
|
$incdir.="]";
|
|
|
my $files = join ("\n",@sources);
|
my $files = join ("\n",@sources);
|
|
|
|
|
|
|
#add mem initial file to sources
|
#add mem initial file to sources
|
my $mem_files="";
|
my $mem_files="";
|
my @initial_files = File::Find::Rule->file()
|
my @initial_files = File::Find::Rule->file()
|
->name( '*.mem')
|
->name( '*.mem')
|
->in( "$target_dir/sw" );
|
->in( "$target_dir/sw" );
|
mkpath("$target_dir/Vivado/xilinx_mem",1,01777) unless -f "$target_dir/Vivado/xilinx_mem";
|
mkpath("$target_dir/Vivado/xilinx_mem",1,01777) unless -f "$target_dir/Vivado/xilinx_mem";
|
foreach my $f (@initial_files){
|
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/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
|
# /home/alireza/work/hca_git/mpsoc_work/MPSOC/newAdder/sw/tile0/RAM/ram0.mif fpr mpsoc
|
my @m = split('\/sw\/',$f );
|
my @m = split('\/sw\/',$f );
|
my $d = $m[-1];#take the last file path name after /sw/
|
my $d = $m[-1];#take the last file path name after /sw/
|
$d=~ s/RAM//g; #remove RAM
|
$d=~ s/RAM//g; #remove RAM
|
$d=~ s/\///g; #remove /
|
$d=~ s/\///g; #remove /
|
$d = "tile0".$d unless($m[-1]=~/^tile/); #add tile0 to soc
|
$d = "tile0".$d unless($m[-1]=~/^tile/); #add tile0 to soc
|
copy($f,"$target_dir/Vivado/xilinx_mem/$d");
|
copy($f,"$target_dir/Vivado/xilinx_mem/$d");
|
$mem_files="$mem_files \$tcl_path/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");
|
add_info($tview,"HDL sources:\n$files\nMem sources:\n$mem_files\n");
|
#make tcl file
|
#make tcl file
|
my $tcl="
|
my $tcl="
|
#Get tcl shell path relative to current script
|
#Get tcl shell path relative to current script
|
set tcl_path [file dirname [info script]]
|
set tcl_path [file dirname [info script]]
|
set Dir \"\$tcl_path/..\"
|
set Dir \"\$tcl_path/..\"
|
";
|
";
|
|
|
$tcl=$tcl."set projectName $name";
|
$tcl=$tcl."set projectName $name";
|
|
|
$tcl =$tcl."
|
$tcl =$tcl."
|
source \"\$tcl_path/board_property.tcl\"
|
source \"\$tcl_path/board_property.tcl\"
|
#Create output directory and clear contents
|
#Create output directory and clear contents
|
set outputdir \"\$tcl_path/xilinx_compile\"";
|
set outputdir \"\$tcl_path/xilinx_compile\"";
|
$tcl =$tcl.'
|
$tcl =$tcl.'
|
file mkdir $outputdir
|
file mkdir $outputdir
|
set files [glob -nocomplain "$outputdir/*"]
|
set files [glob -nocomplain "$outputdir/*"]
|
if {[llength $files] != 0} {
|
if {[llength $files] != 0} {
|
puts "deleting contents of $outputdir"
|
puts "deleting contents of $outputdir"
|
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents
|
file delete -force {*}[glob -directory $outputdir *]; # clear folder contents
|
} else {
|
} else {
|
puts "$outputdir is empty"
|
puts "$outputdir is empty"
|
}
|
}
|
|
|
#Create project
|
#Create project
|
create_project $projectName $outputdir
|
create_project $projectName $outputdir
|
|
|
set_project_properties
|
set_project_properties
|
|
|
#add source files to Vivado project
|
#add source files to Vivado project
|
';
|
';
|
|
|
#get top level port names
|
#get top level port names
|
#get boards pin list
|
#get boards pin list
|
my $top_v= "$target_dir/src_verilog/Top.v";
|
my $top_v= "$target_dir/src_verilog/Top.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!",'error');
|
message_dialog("Error: Could not load the board pin list. The Top.v does not exist!",'error');
|
$window->destroy;
|
$window->destroy;
|
}
|
}
|
|
|
|
|
my @ports=verilog_file_get_ports_list(read_verilog_file($top_v),"Top");
|
my @ports=verilog_file_get_ports_list(read_verilog_file($top_v),"Top");
|
|
|
#get board tcl
|
#get board tcl
|
my $board_name=$self->object_get_attribute('compile','board');
|
my $board_name=$self->object_get_attribute('compile','board');
|
my @tcls= glob("../boards/$vendor/$board_name/*.tcl");
|
my @tcls= glob("../boards/$vendor/$board_name/*.tcl");
|
foreach my $f (@tcls){
|
foreach my $f (@tcls){
|
copy($f,"$target_dir/Vivado");
|
copy($f,"$target_dir/Vivado");
|
}
|
}
|
|
|
#get board xdc
|
#get board xdc
|
my @xdcs= glob("../boards/$vendor/$board_name/*.xdc");
|
my @xdcs= glob("../boards/$vendor/$board_name/*.xdc");
|
my $i=1;
|
my $i=1;
|
|
|
foreach my $f (@xdcs){
|
foreach my $f (@xdcs){
|
my $out="";
|
my $out="";
|
#capture file content
|
#capture file content
|
my $string= load_file($f);
|
my $string= load_file($f);
|
my @lines=split('\n',$string);
|
my @lines=split('\n',$string);
|
#make sure lines describing the port name are not comment
|
#make sure lines describing the port name are not comment
|
foreach my $l (@lines){
|
foreach my $l (@lines){
|
foreach my $p (@ports){
|
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\}\[]/);
|
$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";
|
$out=$out."$l\n";
|
}
|
}
|
my ($fname,$fpath,$fsuffix) = fileparse("$f",qr"\..[^.]*$");
|
my ($fname,$fpath,$fsuffix) = fileparse("$f",qr"\..[^.]*$");
|
my $xdc_file = "$target_dir/Vivado/$fname.xdc";
|
my $xdc_file = "$target_dir/Vivado/$fname.xdc";
|
#save new xdc file
|
#save new xdc file
|
save_file($xdc_file,$out);
|
save_file($xdc_file,$out);
|
#add xdc to tcl file
|
#add xdc to tcl file
|
$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/$fname.xdc\n";
|
$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/$fname.xdc\n";
|
$i++;
|
$i++;
|
}
|
}
|
|
|
#internal clock constrain
|
#internal clock constrain
|
my $clk_xdc=get_clk_constrain_file($self);
|
my $clk_xdc=get_clk_constrain_file($self);
|
#save_file ("$target_dir/clk.xdc",$clk_xdc);
|
#save_file ("$target_dir/clk.xdc",$clk_xdc);
|
#$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/clk.xdc\n";
|
#$tcl =$tcl."add_files -fileset constrs_1 \$tcl_path/clk.xdc\n";
|
|
|
|
|
|
|
$tcl =$tcl."add_files ";
|
$tcl =$tcl."add_files ";
|
#add hdl sources
|
#add hdl sources
|
foreach my $f (@sources){
|
foreach my $f (@sources){
|
my $p =cut_dir_path($f,'src_verilog');
|
my $p =cut_dir_path($f,'src_verilog');
|
$tcl =$tcl." \$Dir/src_verilog/$p ";
|
$tcl =$tcl." \$Dir/src_verilog/$p ";
|
}
|
}
|
$tcl =$tcl."\n";
|
$tcl =$tcl."\n";
|
|
|
$tcl =$tcl."#add memory initial files to Vivado project
|
$tcl =$tcl."#add memory initial files to Vivado project
|
add_files -norecurse $mem_files" if(length($mem_files)>3);
|
add_files -norecurse $mem_files" if(length($mem_files)>3);
|
|
|
|
|
$tcl =$tcl."\n set_property \"top\" \"Top\" [current_fileset]\n";
|
$tcl =$tcl."\n set_property \"top\" \"Top\" [current_fileset]\n";
|
$tcl =$tcl."
|
$tcl =$tcl."
|
update_compile_order -fileset sources_1
|
update_compile_order -fileset sources_1
|
#launch synthesis
|
#launch synthesis
|
|
|
# Make all reset syncron
|
# Make all reset syncron
|
set_property verilog_define {{SYNC_RESET_MODE}} [current_fileset]
|
set_property verilog_define {{SYNC_RESET_MODE}} [current_fileset]
|
|
|
# include source dirs
|
# include source dirs
|
$incdir
|
$incdir
|
set_property include_dirs \$include_dir_list [current_fileset]
|
set_property include_dirs \$include_dir_list [current_fileset]
|
|
|
launch_runs synth_1
|
launch_runs synth_1
|
wait_on_run synth_1
|
wait_on_run synth_1
|
#Run implementation and generate bitstream
|
#Run implementation and generate bitstream
|
set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1]
|
set_property STEPS.PHYS_OPT_DESIGN.IS_ENABLED true [get_runs impl_1]
|
launch_runs impl_1 -to_step write_bitstream
|
launch_runs impl_1 -to_step write_bitstream
|
wait_on_run impl_1
|
wait_on_run impl_1
|
puts \"Implementation done!\"
|
puts \"Implementation done!\"
|
";
|
";
|
|
|
|
|
$tcl =$tcl."\nexit";
|
$tcl =$tcl."\nexit";
|
#creat make_project tcl file
|
#creat make_project tcl file
|
save_file ("$target_dir/Vivado/make_project.tcl",$tcl);
|
save_file ("$target_dir/Vivado/make_project.tcl",$tcl);
|
|
|
my $error =run_vivado ($self,$target_dir,$tview,"$target_dir/Vivado/make_project.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);
|
add_colored_info($tview,"Vivado compilation is done successfully in $target_dir/Vivado!\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 Vivado compilation!",'error');
|
message_dialog("Error in Vivado compilation!",'error');
|
}
|
}
|
}
|
}
|
|
|
|
|
}
|
}
|
|
|
|
|
sub run_vivado {
|
sub run_vivado {
|
my ($self,$target_dir,$tview,$tcl)=@_;
|
my ($self,$target_dir,$tview,$tcl)=@_;
|
my $error=0;
|
my $error=0;
|
#start compilation
|
#start compilation
|
my $vivado_bin= $self->object_get_attribute('compile','vivado bin');
|
my $vivado_bin= $self->object_get_attribute('compile','vivado bin');
|
add_info($tview, "Start compilation using vivado.....\n");
|
add_info($tview, "Start compilation using vivado.....\n");
|
my @compilation_command =(
|
my @compilation_command =(
|
"cd \"$target_dir/Vivado/\" \n xterm -e bash -c '$vivado_bin/vivado -mode tcl -source $tcl'"
|
"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");
|
save_file("$target_dir/Vivado/run.sh", "#!/bin/bash \n $vivado_bin/vivado -mode tcl -source $tcl");
|
|
|
|
|
my $log="$target_dir/Vivado/vivado.log";
|
my $log="$target_dir/Vivado/vivado.log";
|
#unlink $log;
|
#unlink $log;
|
|
|
foreach my $cmd (@compilation_command){
|
foreach my $cmd (@compilation_command){
|
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($exit){
|
if($exit){
|
$error=1;
|
$error=1;
|
add_colored_info($tview, "$stdout\n",'red') if(defined $stdout);
|
add_colored_info($tview, "$stdout\n",'red') if(defined $stdout);
|
add_colored_info($tview, "$stderr\n",'red') if(defined $stderr);
|
add_colored_info($tview, "$stderr\n",'red') if(defined $stderr);
|
}
|
}
|
|
|
}
|
}
|
|
|
#check vivado.log for error
|
#check vivado.log for error
|
my $r;
|
my $r;
|
open my $fd, "<" , $log or $r=$!;
|
open my $fd, "<" , $log or $r=$!;
|
if(defined $r ) {
|
if(defined $r ) {
|
add_colored_info($tview, "could not open $log to check errors: $r\n",'red');
|
add_colored_info($tview, "could not open $log to check errors: $r\n",'red');
|
$error=1;
|
$error=1;
|
}
|
}
|
else{
|
else{
|
|
|
#check error
|
#check error
|
while (my $line = <$fd>) {
|
while (my $line = <$fd>) {
|
chomp $line;
|
chomp $line;
|
if( $line =~ /ERROR:/){
|
if( $line =~ /ERROR:/){
|
add_colored_info($tview, "$line\n",'red');
|
add_colored_info($tview, "$line\n",'red');
|
$error=1;
|
$error=1;
|
}
|
}
|
}
|
}
|
|
|
#check warning
|
#check warning
|
close($fd);
|
close($fd);
|
open $fd, "<" , $log;
|
open $fd, "<" , $log;
|
#print "$log\n";
|
#print "$log\n";
|
if($error==0){
|
if($error==0){
|
while (my $line = <$fd>) {
|
while (my $line = <$fd>) {
|
chomp $line;
|
chomp $line;
|
if( $line =~ /^\s*WARNING:/){
|
if( $line =~ /^\s*WARNING:/){
|
add_info($tview, "$line\n");
|
add_info($tview, "$line\n");
|
|
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
#check critical warning
|
#check critical warning
|
close($fd);
|
close($fd);
|
open $fd, "<" , $log;
|
open $fd, "<" , $log;
|
#print "$log\n";
|
#print "$log\n";
|
if($error==0){
|
if($error==0){
|
while (my $line = <$fd>) {
|
while (my $line = <$fd>) {
|
chomp $line;
|
chomp $line;
|
if( $line =~ /^\s*CRITICAL WARNING:/){
|
if( $line =~ /^\s*CRITICAL WARNING:/){
|
add_colored_info($tview, "$line\n",'green');
|
add_colored_info($tview, "$line\n",'green');
|
}
|
}
|
}
|
}
|
}
|
}
|
close($fd);
|
close($fd);
|
}
|
}
|
return $error;
|
return $error;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
sub modelsim_compilation{
|
sub modelsim_compilation{
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
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',FALSE,1);
|
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
|
#creat modelsim dir
|
|
|
my $model="$target_dir/Modelsim";
|
my $model="$target_dir/Modelsim";
|
unlink("$model/model.tcl");
|
unlink("$model/model.tcl");
|
rmtree("$target_dir/rtl_work");
|
rmtree("$target_dir/rtl_work");
|
mkpath("$model/rtl_work",1,01777);
|
mkpath("$model/rtl_work",1,01777);
|
|
|
my ($app,$table,$tview,$window) = software_main("$target_dir/Modelsim",undef);
|
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,$tview) unless (-f "$target_dir/Modelsim/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");
|
$app->refresh_source("$target_dir/Modelsim/testbench.v");
|
|
|
|
|
|
|
add_info($tview,"create Modelsim dir in $target_dir\n");
|
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 $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");
|
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");
|
if ($response eq 'yes') {
|
if ($response eq 'yes') {
|
gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview);
|
gen_modelsim_soc_testbench ($self,$name,$top,$target_dir,$tview);
|
$app->refresh_source("$target_dir/Modelsim/testbench.v");
|
$app->refresh_source("$target_dir/Modelsim/testbench.v");
|
}
|
}
|
});
|
});
|
|
|
$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
|
#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");
|
add_info($tview,"Get the list of all Verilog files in src_verilog folder\n");
|
my @files = File::Find::Rule->file()
|
my @files = File::Find::Rule->file()
|
->name( '*.v','*.V','*.sv' )
|
->name( '*.v','*.V','*.sv' )
|
->in( "$target_dir/src_verilog" );
|
->in( "$target_dir/src_verilog" );
|
|
|
#get list of all verilog files in src_sim folder
|
#get list of all verilog files in src_sim folder
|
my @sim_files = File::Find::Rule->file()
|
my @sim_files = File::Find::Rule->file()
|
->name( '*.v','*.V','*.sv' )
|
->name( '*.v','*.V','*.sv' )
|
->in( "$target_dir/src_sim" );
|
->in( "$target_dir/src_sim" );
|
push (@files, @sim_files);
|
push (@files, @sim_files);
|
#add testnemch.v
|
#add testnemch.v
|
push (@files, "$target_dir/Modelsim/testbench.v");
|
push (@files, "$target_dir/Modelsim/testbench.v");
|
|
|
#create a file list
|
#create a file list
|
my $tt =create_file_list($target_dir,\@files,'modelsim');
|
my $tt =create_file_list($target_dir,\@files,'modelsim');
|
save_file("$target_dir/Modelsim/file_list.f", "$tt");
|
save_file("$target_dir/Modelsim/file_list.f", "$tt");
|
|
|
|
|
#create modelsim.tcl file
|
#create modelsim.tcl file
|
my $tcl="#!/usr/bin/tclsh
|
my $tcl="#!/usr/bin/tclsh
|
|
|
|
|
transcript on
|
transcript on
|
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
|
|
|
|
|
vlog +acc=rn -F $target_dir/Modelsim/file_list.f
|
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 model.tcl, run.sh files\n");
|
add_info($tview,"Create model.tcl, run.sh files\n");
|
save_file ("$model/model.tcl",$tcl);
|
save_file ("$model/model.tcl",$tcl);
|
my $modelsim_bin= $self->object_get_attribute('compile','modelsim_bin');
|
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";
|
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);
|
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->ask_to_save_changes();
|
$app->ask_to_save_changes();
|
|
|
|
|
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();
|
}
|
}
|
|
|
|
|
# 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 create_file_list {
|
sub create_file_list {
|
my ($target_dir,$files_ref, $platform)=@_;
|
my ($target_dir,$files_ref, $platform)=@_;
|
my @ff=@{$files_ref} if(defined $files_ref);
|
my @ff=@{$files_ref} if(defined $files_ref);
|
my $pakages="";
|
my $pakages="";
|
my $file_list="";
|
my $file_list="";
|
my $include="";
|
my $include="";
|
|
|
my %paths;
|
my %paths;
|
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);
|
@ff =uniq( @ff);
|
|
|
foreach my $file (@files) {
|
foreach my $file (@files) {
|
my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$");
|
my ($name,$path,$suffix) = fileparse("$file",qr"\..[^.]*$");
|
#print "$path\n";
|
#print "$path\n";
|
my $remove="$target_dir/";
|
my $remove="$target_dir/";
|
$path =~ s/$remove//;
|
$path =~ s/$remove//;
|
$paths{$path}=1;
|
$paths{$path}=1;
|
|
|
#put packages at the top of the list
|
#put packages at the top of the list
|
if(check_file_has_string($file,'endpackage')){
|
if(check_file_has_string($file,'endpackage')){
|
$pakages.="../${path}${name}$suffix\n" if($platform eq 'modelsim');
|
$pakages.="../${path}${name}$suffix\n" if($platform eq 'modelsim');
|
$pakages.="./${name}$suffix\n" if($platform eq 'verilator');
|
$pakages.="./${name}$suffix\n" if($platform eq 'verilator');
|
} else{
|
} else{
|
$file_list.= "../${path}${name}$suffix\n"if($platform eq 'modelsim');
|
$file_list.= "../${path}${name}$suffix\n"if($platform eq 'modelsim');
|
$file_list.= "./${name}$suffix\n"if($platform eq 'verilator');
|
$file_list.= "./${name}$suffix\n"if($platform eq 'verilator');
|
}
|
}
|
}
|
}
|
foreach my $p (sort keys %paths){
|
foreach my $p (sort keys %paths){
|
$include.="+incdir+../$p\n";
|
$include.="+incdir+../$p\n";
|
}
|
}
|
|
|
return "$include\n$pakages\n$file_list";
|
return "$include\n$pakages\n$file_list";
|
}
|
}
|
|
|
|
|
sub verilator_compilation {
|
sub verilator_compilation {
|
my ($top_ref,$target_dir,$outtext,$cpu_num)=@_;
|
my ($top_ref,$target_dir,$outtext,$cpu_num)=@_;
|
$cpu_num = 1 if (!defined $cpu_num);
|
$cpu_num = 1 if (!defined $cpu_num);
|
my %tops = %{$top_ref};
|
my %tops = %{$top_ref};
|
#creat verilator dir
|
#creat verilator dir
|
add_info($outtext,"create verilator dir in $target_dir\n");
|
add_info($outtext,"create verilator dir in $target_dir\n");
|
my $verilator="$target_dir/verilator";
|
my $verilator="$target_dir/verilator";
|
|
|
rmtree("$verilator");
|
rmtree("$verilator");
|
mkpath("$verilator",1,01777);
|
mkpath("$verilator",1,01777);
|
|
|
my @ff = ("$target_dir/src_verilog");
|
my @ff = ("$target_dir/src_verilog");
|
push (@ff,"$target_dir/src_verilator") if (-d "$target_dir/src_verilator");
|
push (@ff,"$target_dir/src_verilator") if (-d "$target_dir/src_verilator");
|
push (@ff,"$target_dir/src_sim") if (-d "$target_dir/src_sim");
|
push (@ff,"$target_dir/src_sim") if (-d "$target_dir/src_sim");
|
|
|
#create a file list
|
#create a file list
|
add_info($outtext,"make a file list containig all RTL modules\n");
|
add_info($outtext,"make a file list containig all RTL modules\n");
|
my $tt =create_file_list($target_dir,\@ff,'verilator');
|
my $tt =create_file_list($target_dir,\@ff,'verilator');
|
save_file("$verilator/file_list.f", "$tt");
|
save_file("$verilator/file_list.f", "$tt");
|
|
|
#check if -Wno-TIMESCALEMOD flag is supported"
|
#check if -Wno-TIMESCALEMOD flag is supported"
|
my $flag="";
|
my $flag="";
|
# my $cmd ="verilator --version | head -n1 | cut -d\" \" -f2";
|
# my $cmd ="verilator --version | head -n1 | cut -d\" \" -f2";
|
# my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
# my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
|
|
# my $current_v=$stdout;
|
# my $current_v=$stdout;
|
# $current_v =~ s/[^0-9.]//g;
|
# $current_v =~ s/[^0-9.]//g;
|
# if (defined $current_v){
|
# if (defined $current_v){
|
# $cmd = "printf \'%s\n\' \"4.0.0\" \"$current_v\" | sort -V | head -n1";
|
# $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);
|
# my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout($cmd);
|
# $stdout =~ s/[^0-9.]//g;
|
# $stdout =~ s/[^0-9.]//g;
|
# if ($stdout eq "4.0.0" ){
|
# 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");
|
# 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";
|
# $flag.="-Wno-TIMESCALEMOD";
|
# }else{
|
# }else{
|
# add_info($outtext, "Verilator vesrion is $current_v\n");
|
# add_info($outtext, "Verilator vesrion is $current_v\n");
|
# }
|
# }
|
# }
|
# }
|
my $pdir = get_project_dir();
|
my $pdir = get_project_dir();
|
my $tmp = "$pdir/mpsoc/perl_gui/lib/verilog/tmp.v";
|
my $tmp = "$pdir/mpsoc/perl_gui/lib/verilog/tmp.v";
|
my $cmd = "verilator --lint-only $tmp -Wno-TIMESCALEMOD";
|
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){ #-Wno-TIMESCALEMOD not supported
|
if(length $stderr>1){ #-Wno-TIMESCALEMOD not supported
|
#add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error.
|
#add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error.
|
}else {
|
}else {
|
#add_info($outtext,"compile verilator with -Wno-TIMESCALEMOD\n");
|
#add_info($outtext,"compile verilator with -Wno-TIMESCALEMOD\n");
|
$flag.="-Wno-TIMESCALEMOD";
|
$flag.="-Wno-TIMESCALEMOD";
|
}
|
}
|
|
|
#run verilator
|
#run verilator
|
my $jobs=0; #a counter to limit the number of paralle process
|
my $jobs=0; #a counter to limit the number of paralle process
|
my $make_lib="";
|
my $make_lib="";
|
$cmd="cd \"$verilator\"; ";
|
$cmd="cd \"$verilator\"; ";
|
my $vrun="#!/bin/bash
|
my $vrun="#!/bin/bash
|
cd \"$verilator\"
|
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 $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);
|
my $length = scalar (keys %tops);
|
foreach my $top (sort keys %tops) {
|
foreach my $top (sort keys %tops) {
|
add_colored_info($outtext,"Generate $top Verilator model from $tops{$top} file\n",'green');
|
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 & ";
|
$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";
|
$vrun.="verilator -f ./file_list.f --cc $tops{$top} --prefix \"$top\" $flag -O3 -CFLAGS -O3 &\n";
|
|
|
$make_lib.="make lib$jobs &\n";
|
$make_lib.="make lib$jobs &\n";
|
$jobs++;
|
$jobs++;
|
|
|
if( $jobs % $cpu_num == 0 || $jobs == $length){
|
if( $jobs % $cpu_num == 0 || $jobs == $length){
|
$vrun.="wait\n"; $make_lib.="wait\n"; $cmd.="wait\n";
|
$vrun.="wait\n"; $make_lib.="wait\n"; $cmd.="wait\n";
|
add_info($outtext,"$cmd\n");
|
add_info($outtext,"$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_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error.
|
add_info($outtext,"$stderr\n"); #verilator compain some ignoerabe warnning as error.
|
}else {
|
}else {
|
add_info($outtext,"$stdout\n");
|
add_info($outtext,"$stdout\n");
|
}
|
}
|
$cmd="cd \"$verilator\"; ";
|
$cmd="cd \"$verilator\"; ";
|
}
|
}
|
}
|
}
|
|
|
|
|
|
|
#check if verilator model has been generated
|
#check if verilator model has been generated
|
foreach my $top (sort keys %tops) {
|
foreach my $top (sort keys %tops) {
|
|
|
$vrun.="
|
$vrun.="
|
if ! [ -f $verilator/obj_dir/$top.cpp ]; then
|
if ! [ -f $verilator/obj_dir/$top.cpp ]; then
|
echo \"Failed to generate: $verilator/obj_dir/$top.cpp \"
|
echo \"Failed to generate: $verilator/obj_dir/$top.cpp \"
|
exit 1
|
exit 1
|
fi
|
fi
|
";
|
";
|
|
|
if (-f "$verilator/obj_dir/$top.cpp"){#succsess
|
if (-f "$verilator/obj_dir/$top.cpp"){#succsess
|
|
|
|
|
}else {
|
}else {
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
#generate makefile
|
#generate makefile
|
gen_verilator_makefile($top_ref,"$verilator/obj_dir/Makefile");
|
gen_verilator_makefile($top_ref,"$verilator/obj_dir/Makefile");
|
|
|
$vrun.=" echo \"Verilator modules are generated successfully\".
|
$vrun.=" echo \"Verilator modules are generated successfully\".
|
|
|
cd $verilator/obj_dir/
|
cd $verilator/obj_dir/
|
|
|
#run make file
|
#run make file
|
$make_lib
|
$make_lib
|
|
|
make sim
|
make sim
|
#done
|
#done
|
";
|
";
|
|
|
|
|
save_file ("$verilator/verilate.sh",$vrun);
|
save_file ("$verilator/verilate.sh",$vrun);
|
#copy topology connection header files
|
#copy topology connection header files
|
my $project_dir = get_project_dir();
|
my $project_dir = get_project_dir();
|
$project_dir= "$project_dir/mpsoc";
|
$project_dir= "$project_dir/mpsoc";
|
my $src_verilator_dir="$project_dir/src_verilator";
|
my $src_verilator_dir="$project_dir/src_verilator";
|
my @files = File::Find::Rule->file()
|
my @files = File::Find::Rule->file()
|
->name( '*.h')
|
->name( '*.h')
|
->in( "$src_verilator_dir" );
|
->in( "$src_verilator_dir" );
|
copy_file_and_folders (\@files,$project_dir,"$verilator/obj_dir/");
|
copy_file_and_folders (\@files,$project_dir,"$verilator/obj_dir/");
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
sub verilator_compilation_win {
|
sub verilator_compilation_win {
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
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_txview();
|
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");
|
$mtable->attach($load,8,9,9,10,'shrink','shrink',2,2);
|
$mtable->attach($load,8,9,9,10,'shrink','shrink',2,2);
|
|
|
$mtable->attach_defaults ($outbox ,0, 10, 4,9);
|
$mtable->attach_defaults ($outbox ,0, 10, 4,9);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
|
$mtable->attach($back,2,3,9,10,'shrink','shrink',2,2);
|
|
|
|
|
|
|
|
|
$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);
|
|
|
});
|
});
|
$next-> signal_connect("clicked" => sub{
|
$next-> signal_connect("clicked" => sub{
|
|
|
$window->destroy;
|
$window->destroy;
|
verilator_testbench($self,$name,$top,$target_dir,$vendor);
|
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 $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 $sw_path = "$target_dir/sw";
|
my %params = soc_get_all_parameters($self);
|
my %params = soc_get_all_parameters($self);
|
my $verilator = soc_generate_verilator ($self,$sw_path,"verilator_$n",\%params);
|
my $verilator = soc_generate_verilator ($self,$sw_path,"verilator_$n",\%params);
|
my %tops;
|
my %tops;
|
$tops{"Vtop"}= "--top-module verilator_$n";
|
$tops{"Vtop"}= "--top-module verilator_$n";
|
my $target_verilator_dr ="$target_dir/src_verilator";
|
my $target_verilator_dr ="$target_dir/src_verilator";
|
mkpath("$target_verilator_dr",1,01777);
|
mkpath("$target_verilator_dr",1,01777);
|
save_file ("$target_verilator_dr/verilator_${n}.sv",$verilator);
|
save_file ("$target_verilator_dr/verilator_${n}.sv",$verilator);
|
|
|
|
|
|
|
|
|
|
|
#$tops{"Vtop"}= "--top-module $name";
|
#$tops{"Vtop"}= "--top-module $name";
|
$result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num);
|
$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,$cpu_num);
|
$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,$cpu_num)=@_;
|
my ($self,$name,$top,$target_dir,$outtext,$cpu_num)=@_;
|
|
|
my $project_dir = get_project_dir();
|
my $project_dir = get_project_dir();
|
$project_dir= "$project_dir/mpsoc";
|
$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/rtl/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' )
|
->in( "$src_verilator_dir" );
|
->in( "$src_verilator_dir" );
|
|
|
#make sure source files have key word 'module'
|
#make sure source files have key word 'module'
|
my @files;
|
my @files;
|
foreach my $p (@files_list){
|
foreach my $p (@files_list){
|
push (@files,$p) if(check_file_has_string($p,'module'));
|
push (@files,$p) if(check_file_has_string($p,'module'));
|
}
|
}
|
copy_file_and_folders (\@files,$project_dir,$target_verilator_dr);
|
copy_file_and_folders (\@files,$project_dir,$target_verilator_dr);
|
|
|
|
|
|
|
#copy src_noc files
|
#copy src_noc files
|
#my @files2;
|
#my @files2;
|
#push (@files2,$src_noc_dir);
|
#push (@files2,$src_noc_dir);
|
#copy_file_and_folders (\@files2,$project_dir,$target_verilog_dr);
|
#copy_file_and_folders (\@files2,$project_dir,$target_verilog_dr);
|
|
|
|
|
#create each tile top module
|
#create each tile top module
|
my $processors_en=0;
|
my $processors_en=0;
|
my $mpsoc=$self;
|
my $mpsoc=$self;
|
my $lisence= get_license_header("verilator_tiles");
|
my $lisence= get_license_header("verilator_tiles");
|
my $warning=autogen_warning();
|
my $warning=autogen_warning();
|
my $verilator=$lisence.$warning;
|
my $verilator=$lisence.$warning;
|
|
|
|
|
# generate NoC parameter file
|
# generate NoC parameter file
|
my ($noc_param,$pass_param)=gen_noc_param_v($self);
|
my ($noc_param,$pass_param)=gen_noc_param_v($self);
|
|
|
my $noc_param_v= " \`ifdef INCLUDE_PARAM \n \n
|
my $noc_param_v= " \`ifdef INCLUDE_PARAM \n \n
|
$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);
|
my %tops = %{$ref_tops};
|
my %tops = %{$ref_tops};
|
|
|
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)= $mpsoc->mpsoc_get_tile_soc_name($tile_num);
|
my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($tile_num);
|
|
|
my $soc=eval_soc($mpsoc,$soc_name,$outtext);
|
my $soc=eval_soc($mpsoc,$soc_name,$outtext);
|
|
|
|
|
my $top=$mpsoc->mpsoc_get_soc($soc_name);
|
my $top=$mpsoc->mpsoc_get_soc($soc_name);
|
my $soc_num= $tile_num;
|
my $soc_num= $tile_num;
|
|
|
|
|
#update core id
|
#update core id
|
$soc->object_add_attribute('global_param','CORE_ID',$tile_num);
|
$soc->object_add_attribute('global_param','CORE_ID',$tile_num);
|
|
|
#update NoC param
|
#update NoC param
|
my $nocparam =$mpsoc->object_get_attribute('noc_param',undef);
|
my $nocparam =$mpsoc->object_get_attribute('noc_param',undef);
|
my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc);
|
my ($NE, $NR, $RAw, $EAw, $Fw) = get_topology_info($mpsoc);
|
my %y=%{$nocparam};
|
my %y=%{$nocparam};
|
$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 %z;
|
|
|
my %param_type= $soc->soc_get_module_param_type($nis[0]);
|
my %param_type= $soc->soc_get_module_param_type($nis[0]);
|
foreach my $p (sort keys %y){
|
foreach my $p (sort keys %y){
|
$z{$p}=$param_type{$p}; #"Parameter";
|
$z{$p}=$param_type{$p}; #"Parameter";
|
}
|
}
|
|
|
|
|
|
|
|
|
$soc->soc_add_instance_param_type($nis[0] ,\%z );
|
$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_verilator ($soc,$sw_path,"tile_$tile",\%params);
|
$verilator = $verilator.soc_generate_verilator ($soc,$sw_path,"tile_$tile",\%params);
|
$tops{"Vtile$tile_num"}= "--top-module tile_$tile";
|
$tops{"Vtile$tile_num"}= "--top-module tile_$tile";
|
|
|
|
|
}
|
}
|
|
|
save_file ("$target_verilator_dr/verilator_tiles.sv",$verilator);
|
save_file ("$target_verilator_dr/verilator_tiles.sv",$verilator);
|
my $result = verilator_compilation (\%tops,$target_dir,$outtext,$cpu_num);
|
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;
|
|
|
}
|
}
|
|
|
|
|
sub gen_verilator_soc_testbench {
|
sub gen_verilator_soc_testbench {
|
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>
|
my $include='#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <string.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 %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' :
|
( $intfc eq 'plug:enable[0]')? 'en' :
|
( $intfc eq 'socket:RxD_sim[0]')? 'rxd':
|
( $intfc eq 'socket:RxD_sim[0]')? 'rxd':
|
'other';
|
'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'){
|
if($key eq 'rxd'){
|
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($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
my @q =split (/RxD_ready_si/,$p);
|
my @q =split (/RxD_ready_si/,$p);
|
$rxds{$id}{p}=$q[0] if( defined $q[1]);
|
$rxds{$id}{p}=$q[0] if( defined $q[1]);
|
$rxds{$id}{top}='top' 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 ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir);
|
my $include2="";
|
my $include2="";
|
$include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0);
|
$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
|
$include
|
$include1
|
$include1
|
#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
|
$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
|
$rxd_info
|
Verilated::commandArgs(argc, argv); // Remember args
|
Verilated::commandArgs(argc, argv); // Remember args
|
top = new Vtop;
|
top = new Vtop;
|
|
|
/********************
|
/********************
|
* initialize input
|
* initialize input
|
*********************/
|
*********************/
|
|
|
$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
|
$rxd_cap_cal
|
if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle
|
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
|
$rxd_wr_cal
|
|
|
|
|
}//if
|
}//if
|
else
|
else
|
{
|
{
|
$PP{clk0}
|
$PP{clk0}
|
|
|
|
|
|
|
}//else
|
}//else
|
|
|
|
|
main_time ++;
|
main_time ++;
|
top->eval();
|
top->eval();
|
}
|
}
|
top->final();
|
top->final();
|
}
|
}
|
|
|
double sc_time_stamp () { // Called by \$time in Verilog
|
double sc_time_stamp () { // Called by \$time in Verilog
|
return main_time;
|
return main_time;
|
}
|
}
|
";
|
";
|
save_file("$dir/testbench.cpp",$main_c);
|
save_file("$dir/testbench.cpp",$main_c);
|
|
|
|
|
|
|
}
|
}
|
|
|
sub eval_soc{
|
sub eval_soc{
|
my ($mpsoc,$soc_name,$outtext)=@_;
|
my ($mpsoc,$soc_name,$outtext)=@_;
|
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 {
|
sub rxd_testbench_verilator_gen {
|
my ($rxds_ref,$dir)=@_;
|
my ($rxds_ref,$dir)=@_;
|
|
|
my $rxd_info='';
|
my $rxd_info='';
|
my $rxd_num=0;
|
my $rxd_num=0;
|
my $rxd_func='';
|
my $rxd_func='';
|
my $rxd_wr_cal='';
|
my $rxd_wr_cal='';
|
my $rxd_cap_cal='';
|
my $rxd_cap_cal='';
|
my $include='';
|
my $include='';
|
|
|
my %rxds=%{$rxds_ref};
|
my %rxds=%{$rxds_ref};
|
|
|
foreach my $rxd (sort keys %rxds){
|
foreach my $rxd (sort keys %rxds){
|
my $n=$rxds{$rxd}{p};
|
my $n=$rxds{$rxd}{p};
|
my $top=$rxds{$rxd}{top};
|
my $top=$rxds{$rxd}{top};
|
$rxd_info.="\\t$rxd_num : ${top}_${n}RXD\\n";
|
$rxd_info.="\\t$rxd_num : ${top}_${n}RXD\\n";
|
|
|
$rxd_func.="
|
$rxd_func.="
|
// we have a character to send to interface $rxd_num
|
// we have a character to send to interface $rxd_num
|
if (sent_table[$rxd_num]!=0 && $top->${n}RxD_ready_sim){
|
if (sent_table[$rxd_num]!=0 && $top->${n}RxD_ready_sim){
|
$top->${n}RxD_din_sim=sent_table[$rxd_num];
|
$top->${n}RxD_din_sim=sent_table[$rxd_num];
|
$top->${n}RxD_wr_sim=1;
|
$top->${n}RxD_wr_sim=1;
|
sent_table[$rxd_num]=0;
|
sent_table[$rxd_num]=0;
|
}else {
|
}else {
|
$top->${n}RxD_wr_sim=0;
|
$top->${n}RxD_wr_sim=0;
|
}
|
}
|
";
|
";
|
$rxd_num++;
|
$rxd_num++;
|
}
|
}
|
|
|
|
|
|
|
if($rxd_num>0){
|
if($rxd_num>0){
|
$rxd_func="
|
$rxd_func="
|
#ifndef RXD_SIM_H
|
#ifndef RXD_SIM_H
|
#define RXD_SIM_H
|
#define RXD_SIM_H
|
#define RXD_NUM $rxd_num // number of rxd input interfaces
|
#define RXD_NUM $rxd_num // number of rxd input interfaces
|
char sent_table[RXD_NUM]={0};
|
char sent_table[RXD_NUM]={0};
|
unsigned char active_rxd_num=0;
|
unsigned char active_rxd_num=0;
|
void write_char_on_RXD( ) {
|
void write_char_on_RXD( ) {
|
$rxd_func
|
$rxd_func
|
}
|
}
|
|
|
int kbhit(void) {
|
int kbhit(void) {
|
struct termios oldt, newt;
|
struct termios oldt, newt;
|
int ch;
|
int ch;
|
int oldf;
|
int oldf;
|
|
|
tcgetattr(STDIN_FILENO, &oldt);
|
tcgetattr(STDIN_FILENO, &oldt);
|
newt = oldt;
|
newt = oldt;
|
newt.c_lflag &= ~(ICANON | ECHO);
|
newt.c_lflag &= ~(ICANON | ECHO);
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
|
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
|
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
|
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
|
|
|
ch = getchar();
|
ch = getchar();
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
fcntl(STDIN_FILENO, F_SETFL, oldf);
|
|
|
if(ch != EOF)
|
if(ch != EOF)
|
{
|
{
|
ungetc(ch, stdin);
|
ungetc(ch, stdin);
|
return 1;
|
return 1;
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void capture_char_on_RXD (){
|
void capture_char_on_RXD (){
|
char c;
|
char c;
|
if(kbhit()){
|
if(kbhit()){
|
c=getchar();
|
c=getchar();
|
if(c=='+'){
|
if(c=='+'){
|
active_rxd_num++;
|
active_rxd_num++;
|
if(active_rxd_num>=$rxd_num) active_rxd_num=0;
|
if(active_rxd_num>=$rxd_num) active_rxd_num=0;
|
printf(\"The active input interface num is \%u\\n\",active_rxd_num);
|
printf(\"The active input interface num is \%u\\n\",active_rxd_num);
|
}else if(c=='-'){
|
}else if(c=='-'){
|
active_rxd_num--;
|
active_rxd_num--;
|
if(active_rxd_num>=$rxd_num) active_rxd_num=($rxd_num-1);
|
if(active_rxd_num>=$rxd_num) active_rxd_num=($rxd_num-1);
|
printf(\"The active input interface num is \%u\\n\",active_rxd_num);
|
printf(\"The active input interface num is \%u\\n\",active_rxd_num);
|
}else{
|
}else{
|
sent_table[active_rxd_num]=c;
|
sent_table[active_rxd_num]=c;
|
}
|
}
|
|
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
";
|
";
|
|
|
|
|
$include .='#include <termios.h>
|
$include .='#include <termios.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
';
|
';
|
$rxd_wr_cal="write_char_on_RXD( );";
|
$rxd_wr_cal="write_char_on_RXD( );";
|
$rxd_cap_cal="capture_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\");"
|
$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");
|
my $rxsim_c=get_license_header("RxDsim.h");
|
$rxsim_c.="$rxd_func";
|
$rxsim_c.="$rxd_func";
|
save_file("$dir/RxDsim.h",$rxsim_c) if($rxd_num > 0);
|
save_file("$dir/RxDsim.h",$rxsim_c) if($rxd_num > 0);
|
|
|
return ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include);
|
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.="
|
$parameter_h.="
|
#define NE $ne
|
#define NE $ne
|
#define NR $nr
|
#define NR $nr
|
";
|
";
|
$parameter_h=$parameter_h.$includ_h;
|
$parameter_h=$parameter_h.$includ_h;
|
|
|
|
|
|
|
my $libh="";
|
my $libh="";
|
my $inst= "";
|
my $inst= "";
|
my $newinst="";
|
my $newinst="";
|
|
|
my $tile_addr="";
|
my $tile_addr="";
|
my $tile_flit_in="";
|
my $tile_flit_in="";
|
my $tile_flit_in_l="";
|
my $tile_flit_in_l="";
|
my $tile_credit="";
|
my $tile_credit="";
|
my $noc_credit="";
|
my $noc_credit="";
|
my $noc_flit_in="";
|
my $noc_flit_in="";
|
my $noc_flit_in_l="";
|
my $noc_flit_in_l="";
|
my $noc_flit_in_wr="";
|
my $noc_flit_in_wr="";
|
my $noc_flit_in_wr_l="";
|
my $noc_flit_in_wr_l="";
|
my $tile_flit_in_wr="";
|
my $tile_flit_in_wr="";
|
my $tile_flit_in_wr_l="";
|
my $tile_flit_in_wr_l="";
|
my $tile_eval="";
|
my $tile_eval="";
|
my $tile_final="";
|
my $tile_final="";
|
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 %rxds;
|
|
|
my $tile_chans="";
|
my $tile_chans="";
|
my $tmp_reg='';
|
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);
|
|
|
|
|
my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($endp);
|
my ($soc_name,$num)= $mpsoc->mpsoc_get_tile_soc_name($endp);
|
if(defined $soc_name) {#we have a conncted tile
|
if(defined $soc_name) {#we have a conncted tile
|
|
|
#get ni instance name
|
#get ni instance name
|
my $ni_name;
|
my $ni_name;
|
my $soc=eval_soc($mpsoc,$soc_name,$tview);
|
my $soc=eval_soc($mpsoc,$soc_name,$tview);
|
my $soc_top=$soc->object_get_attribute('top_ip',undef);
|
my $soc_top=$soc->object_get_attribute('top_ip',undef);
|
my @intfcs=$soc_top->top_get_intfc_list();
|
my @intfcs=$soc_top->top_get_intfc_list();
|
my @instances=$soc->soc_get_all_instances();
|
my @instances=$soc->soc_get_all_instances();
|
foreach my $id (@instances){
|
foreach my $id (@instances){
|
my $category = $soc->soc_get_category($id);
|
my $category = $soc->soc_get_category($id);
|
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";
|
$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";
|
$tile_credit= $tile_credit."\ttile${endp}->${ni_name}_credit_in= noc->ni_credit_out[${endp}];\n";
|
$tile_credit= $tile_credit."\ttile${endp}->${ni_name}_credit_in= noc->ni_credit_out[${endp}];\n";
|
$noc_credit= $noc_credit."\tnoc->ni_credit_in[${endp}] = tile${endp}->${ni_name}_credit_out;\n";
|
$noc_credit= $noc_credit."\tnoc->ni_credit_in[${endp}] = tile${endp}->${ni_name}_credit_out;\n";
|
$noc_flit_in=$noc_flit_in."\tnoc->ni_flit_in [${endp}] = tile${endp}->${ni_name}_flit_out;\n";
|
$noc_flit_in=$noc_flit_in."\tnoc->ni_flit_in [${endp}] = tile${endp}->${ni_name}_flit_out;\n";
|
$noc_flit_in_l=$noc_flit_in_l."\t\t\tnoc->ni_flit_in [${endp}][j] = tile${endp}->${ni_name}_flit_out[j];\n";
|
$noc_flit_in_l=$noc_flit_in_l."\t\t\tnoc->ni_flit_in [${endp}][j] = tile${endp}->${ni_name}_flit_out[j];\n";
|
$noc_flit_in_wr= $noc_flit_in_wr."\tif(tile${endp}->${ni_name}_flit_out_wr) noc->ni_flit_in_wr = noc->ni_flit_in_wr | ((vluint64_t)1<<${endp});\n";
|
$noc_flit_in_wr= $noc_flit_in_wr."\tif(tile${endp}->${ni_name}_flit_out_wr) noc->ni_flit_in_wr = noc->ni_flit_in_wr | ((vluint64_t)1<<${endp});\n";
|
$tile_flit_in_wr=$tile_flit_in_wr."\ttile${endp}->${ni_name}_flit_in_wr= ((noc->ni_flit_out_wr >> ${endp}) & 0x01);\n";
|
$tile_flit_in_wr=$tile_flit_in_wr."\ttile${endp}->${ni_name}_flit_in_wr= ((noc->ni_flit_out_wr >> ${endp}) & 0x01);\n";
|
$noc_flit_in_wr_l= $noc_flit_in_wr_l."\tif(tile${endp}->${ni_name}_flit_out_wr) MY_VL_SETBIT_W(noc->ni_flit_in_wr ,${endp});\n";
|
$noc_flit_in_wr_l= $noc_flit_in_wr_l."\tif(tile${endp}->${ni_name}_flit_out_wr) MY_VL_SETBIT_W(noc->ni_flit_in_wr ,${endp});\n";
|
$tile_flit_in_wr_l=$tile_flit_in_wr_l."\ttile${endp}->${ni_name}_flit_in_wr= (VL_BITISSET_W(noc->ni_flit_out_wr,${endp})>0);\n";
|
$tile_flit_in_wr_l=$tile_flit_in_wr_l."\ttile${endp}->${ni_name}_flit_in_wr= (VL_BITISSET_W(noc->ni_flit_out_wr,${endp})>0);\n";
|
$tile_eval=$tile_eval."\ttile${endp}->eval();\n";
|
$tile_eval=$tile_eval."\ttile${endp}->eval();\n";
|
$tile_final=$tile_final."\ttile${endp}->final();\n";
|
$tile_final=$tile_final."\ttile${endp}->final();\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' :
|
($intfc eq 'plug:enable[0]')? 'en' :
|
($intfc eq 'socket:RxD_sim[0]')? 'rxd':
|
($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);
|
$tile_reset=$tile_reset."\t\ttile${endp}->$p=reset;\n" if $key eq 'reset';
|
$tile_reset=$tile_reset."\t\ttile${endp}->$p=reset;\n" if $key eq 'reset';
|
$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'){
|
if($key eq 'rxd'){
|
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($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
my($id,$range,$type,$intfc_name,$intfc_port)= $soc_top->top_get_port($p);
|
my @q =split (/RxD_ready_si/,$p);
|
my @q =split (/RxD_ready_si/,$p);
|
$rxds{$endp.$id}{p}=$q[0] if( defined $q[1]);
|
$rxds{$endp.$id}{p}=$q[0] if( defined $q[1]);
|
$rxds{$endp.$id}{top}="tile$endp" 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
|
$tmp_reg.="\tunsigned char tmp1 [1024]={0};\n \tunsigned char tmp2 [1024]={0};";
|
$tmp_reg.="\tunsigned char tmp1 [1024]={0};\n \tunsigned char tmp2 [1024]={0};";
|
$tile_chans.="\n // Tile:$endp ($e_addr) is not assigned to any ip. Connet coresponding chan to ground.\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";
|
$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 ($rxd_info, $rxd_num, $rxd_wr_cal,$rxd_cap_cal, $include1)=rxd_testbench_verilator_gen (\%rxds,$dir);
|
my $include2="";
|
my $include2="";
|
$include2 .= '#include "RxDsim.h" // Header file for sending charactor to UART from STDIN' if($rxd_num > 0);
|
$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
|
$include1
|
#include <verilated.h> // Defines common routines
|
#include <verilated.h> // Defines common routines
|
$tmp_reg
|
$tmp_reg
|
|
|
|
|
$libh
|
$libh
|
|
|
|
|
$inst
|
$inst
|
int reset,clk,enable;
|
int reset,clk,enable;
|
|
|
|
|
#include \"parameter.h\"
|
#include \"parameter.h\"
|
void * tile_chan_out[NE];
|
void * tile_chan_out[NE];
|
void * tile_chan_in[NE];
|
void * tile_chan_in[NE];
|
|
|
|
|
|
|
#define CHAN_SIZE sizeof(tile0->ni_chan_in)
|
#define CHAN_SIZE sizeof(tile0->ni_chan_in)
|
|
|
#define conect_r2r(T1,r1,p1,T2,r2,p2) \\
|
#define conect_r2r(T1,r1,p1,T2,r2,p2) \\
|
memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE )
|
memcpy(&router##T1 [r1]->chan_in[p1] , &router##T2 [r2]->chan_out[p2], CHAN_SIZE )
|
|
|
#define connect_r2gnd(T,r,p)\\
|
#define connect_r2gnd(T,r,p)\\
|
memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE)
|
memset(&router##T [r]->chan_in [p],0x00,CHAN_SIZE)
|
|
|
#define connect_r2e(T,r,p,e) \\
|
#define connect_r2e(T,r,p,e) \\
|
memcpy(&router##T [r]->chan_in[p], tile_chan_out[e], CHAN_SIZE );\\
|
memcpy(&router##T [r]->chan_in[p], tile_chan_out[e], CHAN_SIZE );\\
|
memcpy(tile_chan_in[e], &router##T [r]->chan_out[p], CHAN_SIZE )
|
memcpy(tile_chan_in[e], &router##T [r]->chan_out[p], CHAN_SIZE )
|
|
|
|
|
|
|
#include \"topology_top.h\"
|
#include \"topology_top.h\"
|
$include2
|
$include2
|
|
|
/*
|
/*
|
$top_port_info
|
$top_port_info
|
*/
|
*/
|
|
|
|
|
unsigned int main_time = 0; // Current simulation time
|
unsigned int main_time = 0; // Current simulation time
|
|
|
|
|
|
|
void connect_clk_reset_en_all(void){
|
void connect_clk_reset_en_all(void){
|
//clk,reset,enable
|
//clk,reset,enable
|
$tile_reset
|
$tile_reset
|
$tile_clk
|
$tile_clk
|
$tile_en
|
$tile_en
|
connect_routers_reset_clk();
|
connect_routers_reset_clk();
|
}
|
}
|
|
|
void sim_eval_all(void){
|
void sim_eval_all(void){
|
routers_eval();
|
routers_eval();
|
$tile_eval
|
$tile_eval
|
}
|
}
|
|
|
void sim_final_all(void ){
|
void sim_final_all(void ){
|
routers_final();
|
routers_final();
|
$tile_final
|
$tile_final
|
}
|
}
|
|
|
void clk_posedge_event(void) {
|
void clk_posedge_event(void) {
|
|
|
clk = 1; // Toggle clock
|
clk = 1; // 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
|
$rxd_wr_cal
|
connect_clk_reset_en_all();
|
connect_clk_reset_en_all();
|
sim_eval_all();
|
sim_eval_all();
|
}
|
}
|
|
|
|
|
void clk_negedge_event(void){
|
void clk_negedge_event(void){
|
|
|
clk = 0;
|
clk = 0;
|
topology_connect_all_nodes ();
|
topology_connect_all_nodes ();
|
connect_clk_reset_en_all();
|
connect_clk_reset_en_all();
|
sim_eval_all();
|
sim_eval_all();
|
}
|
}
|
|
|
|
|
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
int i,j,x,y;
|
int i,j,x,y;
|
$rxd_info
|
$rxd_info
|
Verilated::commandArgs(argc, argv); // Remember args
|
Verilated::commandArgs(argc, argv); // Remember args
|
Vrouter_new(); // Create instance
|
Vrouter_new(); // Create instance
|
|
|
$newinst
|
$newinst
|
|
|
/********************
|
/********************
|
* initialize input
|
* initialize input
|
*********************/
|
*********************/
|
$tile_chans
|
$tile_chans
|
|
|
reset=1;
|
reset=1;
|
enable=1;
|
enable=1;
|
topology_init();
|
topology_init();
|
|
|
$no_connected
|
$no_connected
|
|
|
$tile_addr
|
$tile_addr
|
|
|
|
|
main_time=0;
|
main_time=0;
|
printf(\"Start Simulation\\n\");
|
printf(\"Start Simulation\\n\");
|
while (!Verilated::gotFinish()) {
|
while (!Verilated::gotFinish()) {
|
$rxd_cap_cal
|
$rxd_cap_cal
|
if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle
|
if ((main_time & 0x3FF)==0) fflush(stdout); // fflush \$dispaly command each 1024 clock cycle
|
if (main_time >= 10 ) reset=0;
|
if (main_time >= 10 ) reset=0;
|
|
|
clk_posedge_event( );
|
clk_posedge_event( );
|
//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
|
//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 .
|
//between modules when the clock .
|
for (i=0;i<2*(SMART_MAX+1);i++) clk_negedge_event( );
|
for (i=0;i<2*(SMART_MAX+1);i++) clk_negedge_event( );
|
|
|
main_time++;
|
main_time++;
|
}//while
|
}//while
|
|
|
// Simulation is done
|
// Simulation is done
|
sim_final_all();
|
sim_final_all();
|
}
|
}
|
|
|
double sc_time_stamp () { // Called by \$time in Verilog
|
double sc_time_stamp () { // Called by \$time in Verilog
|
return main_time;
|
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);
|
|
|
}
|
}
|
|
|
|
|
|
|
sub soc_get_all_parameters {
|
sub soc_get_all_parameters {
|
my $soc=shift;
|
my $soc=shift;
|
my @instances=$soc->soc_get_all_instances();
|
my @instances=$soc->soc_get_all_instances();
|
|
|
my %all_param;
|
my %all_param;
|
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 %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 %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 );
|
if ($vfile_param_type eq "Localparam"){
|
if ($vfile_param_type eq "Localparam"){
|
my $type = $params_type{$p};
|
my $type = $params_type{$p};
|
$type = "Localparam" if (! defined $type);
|
$type = "Localparam" if (! defined $type);
|
$vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam";
|
$vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam";
|
}
|
}
|
|
|
#$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
#$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
#$vfile_param_type= "Localparam" if ($vfile_param_type eq 0);
|
#$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;
|
}
|
}
|
|
|
sub soc_get_all_parameters_order {
|
sub soc_get_all_parameters_order {
|
my $soc=shift;
|
my $soc=shift;
|
my @instances=$soc->soc_get_all_instances();
|
my @instances=$soc->soc_get_all_instances();
|
my $ip = ip->lib_new ();
|
my $ip = ip->lib_new ();
|
my @all_order;
|
my @all_order;
|
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);
|
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 );
|
if ($vfile_param_type eq "Localparam"){
|
if ($vfile_param_type eq "Localparam"){
|
my $type = $params_type{$p};
|
my $type = $params_type{$p};
|
$type = "Localparam" if (! defined $type);
|
$type = "Localparam" if (! defined $type);
|
$vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam";
|
$vfile_param_type = ($type eq 'Parameter')? "Parameter" : "Localparam";
|
}
|
}
|
#$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
#$vfile_param_type= "Parameter" if ($vfile_param_type eq 1);
|
#$vfile_param_type= "Localparam" if ($vfile_param_type eq 0);
|
#$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,$tview)=@_;
|
my ($self,$name,$top,$target_dir,$tview)=@_;
|
my $dir="$target_dir/Modelsim";
|
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 $project_dir = get_project_dir();
|
my $project_dir = get_project_dir();
|
open my $file1, "<", "$project_dir/mpsoc/perl_gui/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);
|
|
|
#get parameters
|
#get parameters
|
my $params_v="";
|
my $params_v="";
|
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 $core_id= $self->object_get_attribute('global_param','CORE_ID');
|
my $core_id= $self->object_get_attribute('global_param','CORE_ID');
|
my $sw_loc = $self->object_get_attribute('global_param','SW_LOC');
|
my $sw_loc = $self->object_get_attribute('global_param','SW_LOC');
|
|
|
$params_v="\tlocalparam\tCORE_ID=$core_id;
|
$params_v="\tlocalparam\tCORE_ID=$core_id;
|
\tlocalparam\tSW_LOC=\"$sw_loc\";\n";
|
\tlocalparam\tSW_LOC=\"$sw_loc\";\n";
|
my %params=soc_get_all_parameters($self);
|
my %params=soc_get_all_parameters($self);
|
my @order= soc_get_all_parameters_order($self);
|
my @order= soc_get_all_parameters_order($self);
|
foreach my $p (@order){
|
foreach my $p (@order){
|
add_text_to_string(\$params_v,"\tlocalparam $p = $params{$p};\n") if(defined $params{$p} );
|
add_text_to_string(\$params_v,"\tlocalparam $p = $params{$p};\n") if(defined $params{$p} );
|
}
|
}
|
}else{ # we are simulating a mpsoc
|
}else{ # we are simulating a mpsoc
|
$params_v= gen_socs_param($self);
|
$params_v= gen_socs_param($self);
|
|
|
|
|
}
|
}
|
|
|
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' : '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);
|
my $f=1;
|
my $f=1;
|
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} $p=1;\n" : "$p=1;\n";
|
$PP{$key1}= (defined $PP{$key1})? "$PP{$key1} $p=1;\n" : "$p=1;\n";
|
$PP{$key0}= (defined $PP{$key0})? "$PP{$key0} $p=0;\n" : "$p=0;\n";
|
$PP{$key0}= (defined $PP{$key0})? "$PP{$key0} $p=0;\n" : "$p=0;\n";
|
|
|
|
|
if (length($range)!=0){
|
if (length($range)!=0){
|
# #replace parameter with their values #
|
# #replace parameter with their values #
|
# my @a= split (/\b/,$range);
|
# my @a= split (/\b/,$range);
|
# print "a=@a\n";
|
# print "a=@a\n";
|
# foreach my $l (@a){
|
# foreach my $l (@a){
|
# my $value=$params{$l};
|
# my $value=$params{$l};
|
# if(defined $value){
|
# if(defined $value){
|
# chomp $value;
|
# chomp $value;
|
# ($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l});
|
# ($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l});
|
# print "($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l}); \n";
|
# print "($range=$range)=~ s/\b$l\b/$value/g if(defined $params{$l}); \n";
|
# }
|
# }
|
# }
|
# }
|
$range = "[ $range ]" ;
|
$range = "[ $range ]" ;
|
}
|
}
|
|
|
|
|
|
|
|
|
|
|
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 $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');
|
my $mpsoc_name=$self->object_get_attribute('mpsoc_name');
|
#if(defined $mpsoc_name){
|
#if(defined $mpsoc_name){
|
if(0){
|
if(0){
|
|
|
|
|
my $top_ip=ip_gen->top_gen_new();
|
my $top_ip=ip_gen->top_gen_new();
|
my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name";
|
my $target_dir = "$ENV{'PRONOC_WORK'}/MPSOC/$mpsoc_name";
|
my $hw_dir = "$target_dir/src_verilog";
|
my $hw_dir = "$target_dir/src_verilog";
|
my $sw_dir = "$target_dir/sw";
|
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_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 $socs_param= gen_socs_param($self);
|
my $global_localparam=get_golal_param_v();
|
my $global_localparam=get_golal_param_v();
|
my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($self);
|
my ($clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port)= get_top_clk_setting($self);
|
|
|
|
|
$test_v.="
|
$test_v.="
|
|
|
$clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port
|
$clk_set, $clk_io_sim,$clk_io_full, $clk_assigned_port
|
|
|
`timescale 1ns/1ps
|
`timescale 1ns/1ps
|
|
|
module testbench;
|
module testbench;
|
|
|
$functions_all
|
$functions_all
|
|
|
$global_localparam
|
$global_localparam
|
|
|
$socs_param
|
$socs_param
|
|
|
$top_port_def
|
$top_port_def
|
|
|
|
|
\t${mpsoc_name} the_${mpsoc_name} (
|
\t${mpsoc_name} the_${mpsoc_name} (
|
$top_io_pass
|
$top_io_pass
|
|
|
\t);
|
\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
|
$global_localparam
|
|
|
$params_v
|
$params_v
|
|
|
$top_port_def
|
$top_port_def
|
|
|
|
|
$name uut (
|
$name uut (
|
$pin_assign
|
$pin_assign
|
);
|
);
|
|
|
//clock defination
|
//clock defination
|
initial begin
|
initial begin
|
forever begin
|
forever begin
|
#5 $PP{clk0}
|
#5 $PP{clk0}
|
#5 $PP{clk1}
|
#5 $PP{clk1}
|
end
|
end
|
end
|
end
|
|
|
|
|
|
|
initial begin
|
initial begin
|
// reset $name module at the start up
|
// reset $name module at the start up
|
$PP{reset1}
|
$PP{reset1}
|
$PP{en1}
|
$PP{en1}
|
$rst_inputs
|
$rst_inputs
|
// deasert the reset after 200 ns
|
// deasert the reset after 200 ns
|
#200
|
#200
|
$PP{reset0}
|
$PP{reset0}
|
|
|
// write your testbench here
|
// write your testbench here
|
|
|
|
|
|
|
|
|
end
|
end
|
|
|
endmodule
|
endmodule
|
";
|
";
|
save_file("$dir/testbench.v",$test_v);
|
save_file("$dir/testbench.v",$test_v);
|
|
|
|
|
|
|
}
|
}
|
|
|
sub verilator_testbench{
|
sub verilator_testbench{
|
my ($self,$name,$top,$target_dir,$vendor)=@_;
|
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');
|
|
|
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 (@_) if((-f "$dir/testbench.cpp")==0);
|
gen_verilator_soc_testbench (@_) if((-f "$dir/testbench.cpp")==0);
|
}
|
}
|
else { # we are compiling a complete NoC-based mpsoc
|
else { # we are compiling a complete NoC-based mpsoc
|
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/obj_dir/Makefile");
|
#copy("../script/verilator_soc_make", "$verilator/obj_dir/Makefile");
|
|
|
|
|
|
|
|
|
|
|
my $make = def_image_button('icons/gen.png','Compile');
|
my $make = def_image_button('icons/gen.png','Compile');
|
my $regen=def_image_button('icons/refresh.png','Regenerate Testbench.cpp');
|
my $regen=def_image_button('icons/refresh.png','Regenerate Testbench.cpp');
|
my $run = def_image_button('icons/run.png','Run');
|
my $run = def_image_button('icons/run.png','Run');
|
my $back=def_image_button('icons/left.png','Previous');
|
my $back=def_image_button('icons/left.png','Previous');
|
|
|
|
|
|
|
$table->attach ($back,1,2,1,2,'shrink','shrink',0,0);
|
$table->attach ($back,1,2,1,2,'shrink','shrink',0,0);
|
$table->attach ($regen,3,4,1,2,'shrink','shrink',0,0);
|
$table->attach ($regen,3,4,1,2,'shrink','shrink',0,0);
|
$table->attach ($make,6, 7, 1,2,'shrink','shrink',0,0);
|
$table->attach ($make,6, 7, 1,2,'shrink','shrink',0,0);
|
$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,$vendor);
|
verilator_compilation_win($self,$name,$top,$target_dir,$vendor);
|
|
|
});
|
});
|
|
|
$regen-> signal_connect("clicked" => sub{
|
$regen-> signal_connect("clicked" => sub{
|
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");
|
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");
|
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->refresh_source("$dir/testbench.cpp");
|
$app->refresh_source("$dir/testbench.cpp");
|
}
|
}
|
});
|
});
|
|
|
|
|
$make -> signal_connect("clicked" => sub{
|
$make -> signal_connect("clicked" => sub{
|
$make->hide;
|
$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->ask_to_save_changes();
|
$app->ask_to_save_changes();
|
copy("$dir/testbench.cpp", "$verilator/obj_dir/testbench.cpp");
|
copy("$dir/testbench.cpp", "$verilator/obj_dir/testbench.cpp");
|
copy("$dir/parameter.h", "$verilator/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");
|
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');
|
my $cpu_num = $self->object_get_attribute('compile', 'cpu_num');
|
$cpu_num = 1 if (!defined $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');
|
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 $length=scalar (keys %tops);
|
my $cmd="";
|
my $cmd="";
|
foreach my $top (sort keys %tops) {
|
foreach my $top (sort keys %tops) {
|
$cmd.= "lib$lib_num & ";
|
$cmd.= "lib$lib_num & ";
|
$lib_num++;
|
$lib_num++;
|
if( $lib_num % $cpu_num == 0 || $lib_num == $length){
|
if( $lib_num % $cpu_num == 0 || $lib_num == $length){
|
$cmd.="wait\n";
|
$cmd.="wait\n";
|
run_make_file("$verilator/obj_dir/",$tview,$cmd);
|
run_make_file("$verilator/obj_dir/",$tview,$cmd);
|
$cmd="";
|
$cmd="";
|
}else {
|
}else {
|
$cmd.=" make ";
|
$cmd.=" make ";
|
}
|
}
|
}
|
}
|
|
|
|
|
#foreach my $top (sort keys %tops) {
|
#foreach my $top (sort keys %tops) {
|
# run_make_file("$verilator/obj_dir/",$tview,"lib$lib_num");
|
# run_make_file("$verilator/obj_dir/",$tview,"lib$lib_num");
|
# $lib_num++;
|
# $lib_num++;
|
#}
|
#}
|
|
|
|
|
|
|
run_make_file("$verilator/obj_dir/",$tview,"sim");
|
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/obj_dir/testbench";
|
my $bin="$verilator/obj_dir/testbench";
|
if (-f $bin){
|
if (-f $bin){
|
my $cmd= "cd \"$verilator/obj_dir/\" \n xterm -e bash -c \"$bin; sleep 5\"";
|
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;
|
|
|