cores-swerv-el2/soc/swerv.config

2610 lines
106 KiB
Plaintext
Raw Permalink Normal View History

2022-03-07 21:08:10 +08:00
#! /usr/bin/env perl
use strict; # Do not turn this off or else
use Data::Dumper;
use Getopt::Long;
use Bit::Vector;
use lib "$ENV{RV_ROOT}/tools";
use JSON;
my ($self) = $0 =~ m/.*\/(\w+)/o;
my @argv_orig = @ARGV;
# Master configuration file
#
# Configuration is perl hash
# Output are define files for various flows
# Verilog (`defines common to RTL/TB)
# Software (#defines)
# Whisper (JSON/#defines)
#
# Default values and valid ranges should be specified
# Can be overridden via the cmd line (-set=name=value-string)
#
# Format of the hash is
# name => VALUE | LIST | HASH
#
# Special name "inside" followed by list .. values must be one of provided list
# Special name "derive" followed by equation to derive
#
# Dump verilog/assembly macros in upper case
my $defines_case = "U";
# Include these macros in verilog (pattern matched)
my @verilog_vars = qw (xlen config_key reset_vec tec_rv_icg numiregs nmi_vec target protection.* testbench.* dccm.* retstack core.* iccm.* btb.* bht.* icache.* pic.* regwidth memmap bus.*);
# Include these macros in assembly (pattern matched)
my @asm_vars = qw (xlen reset_vec nmi_vec target dccm.* iccm.* pic.* memmap testbench.* protection.* core.*);
my @asm_overridable = qw (reset_vec nmi_vec serialio external_data) ;
# Include these macros in PD (pattern matched)
my @pd_vars = qw (physical retstack target btb.* bht.* dccm.* iccm.* icache.* pic.* bus.* reset_vec nmi_vec build_ahb_lite datawidth );
# Dump non-derived/settable vars/values for these vars in stdout :
my @dvars = qw(retstack btb bht core dccm iccm icache pic protection memmap bus);
# Prefix all macros with
my $prefix = "RV_";
# No prefix if keyword has
my $no_prefix = 'RV|TOP|tec_rv_icg|regwidth|clock_period|^datawidth|verilator|SDVT_AHB';
my $vlog_use__wh = 1;
my %regions_used = ();
# Cmd Line options#{{{
our %sets;
our %unsets;
my $help;
my @sets = ();
my @unsets = ();
#Configurations may be changed via the -set option
#
# -set=name=value : Change the default config parameter value (lowercase)\n";
# -unset=name : Remove the default config parameter (lowercase)\n";
# : Do not prepend RV_ prefex to -set/-unset variables\n";
# : multiple -set/-unset options accepted\n\n";
#
my $helpusage = "
Main configuration database for SWERV
This script documents, and generates the {`#} define/include files for verilog/assembly/backend flows
It is run by vsim (with defaults) every time the file changes, or when -config_set=VAR=value options are passed to vsim
This script can be run stand-alone by processes not running vsim
User options:
-target = {default, default_ahb, high_perf, typical_pd}
use default settings for one of the targets
-set=var=value
set arbitrary variable(parameter) to a value
-unset=var
unset any definitions for var
-snapshot=name
name the configuration (only if no -target specified)
Parameters that can be set by the end user:
-set=ret_stack_size = {2, 3, 4, ... 8}
size of return stack
-set=btb_enable = {0,1}
BTB enabled
-set=btb_fullya = {0,1}
BTB Fully set-associative
-set=btb_size = { 8, 16, 32, 64, 128, 256, 512 }
size of branch target buffer
-set=bht_size = {32, 64, 128, 256, 512, 1024, 2048}
size of branch history buffer
-set=div_bit = {1,2,3,4}
number of bits to process each cycle
-set=div_new = {0,1}
new div algorithm
-set=dccm_enable = {0,1}
DCCM enabled
-set=dccm_num_banks = {2, 4}
DCCM number of banks
-set=dccm_region = { 0x0, 0x1, ... 0xf }
number of 256Mb memory region containig DCCM
-set=dccm_offset = hexadecimal
offset (in bytes) of DCCM witin dccm_region
dccm address will be: 256M * dccm_region + dccm_offset\", and that must be aligned
to the dccm size or the next larger power of 2 if size is not a power of 2
-set=dccm_size = { 4, 8, 16, 32, 48, 64, 128, 256, 512 } kB
size of DCCM
-set=dma_buf_depth = {2,4,5}
DMA buffer depth
-set=fast_interrupt_redirect = {0, 1}
Fast interrupt redirect mechanism
-set=iccm_enable = { 0, 1 }
whether or not ICCM is enabled
-set=icache_enable = { 0, 1 }
whether or not icache is enabled
-set=icache_waypack = { 0, 1 }
whether or not icache packing is enabled
-set=icache_ecc = { 0, 1 }
whether or not icache has ecc - EXPENSIVE 30% sram growth
default: icache_ecc==0 (parity)
-set=icache_size = { 8, 16, 32, 64, 128, 256 } kB
size of icache
-set=icache_2banks = {0,1}
Enable 2 banks for icache
-set=icache_num_ways { 2,4}
Number of ways in icache
-set=icache_bypass_enable = {0,1}
Enable Icache data bypass buffer
-set=icache_num_bypass = {1..8}
Number of entries in bypass buffer
-set=icache_num_tag_bypass = {1..8}
Number of entries in bypass buffer
-set=icache_tag_bypass_enable = {0,1}
Enable icache tag bypass buffer
-set=iccm_region = { 0x0, 0x1, ... 0xf }
number of 256Mb memory region containing ICCM
-set=iccm_offset = hexadecimal
offcet (in bytes) of ICCM within iccm_region
iccm address will be: \"256M * iccm_region + iccm_offset\", and that must be aligned
to the iccm size or the next larger power of 2 if size is not a power of 2
-set=iccm_size = { 4 , 8 , 16 , 32, 64, 128, 256, 512 } kB
size of ICCM
-set=iccm_num_banks = {2,4,8,16}
Number of ICCM banks
-set=lsu_stbuf_depth = {2,4,8 }
LSU stbuf depth
-set=lsu_num_nbload = {2,4,8 }
LSU number of outstanding Non Blocking loads
-set=load_to_use_plus1 = {0 1}
Load to use latency (fast or +1cycle)
-set=pic_2cycle = { 0, 1 }
whether or not 2-cycle PIC is enabled (2 cycle pic may result
in an overall smaller cycle time)
-set=pic_region = { 0x0, 0x1, ... 0xf }
number of 256Mb memory region containing PIC memory-mapped registers
-set=pic_offset = hexadecial
offset (in bytes) of PIC within pic_region
pic address will be: \"256M * pic_region + pic_offset\", and that must be aligned
to the pic size or the next larger power of 2 if size is not a power of 2
-set=pic_size = { 32, 64, 128, 256 } kB
size of PIC
-set=pic_total_int = { 1, 2, 3, ..., 255 }
number of interrupt sources in PIC
-set=dma_buf_depth = {2,4,5}
DMA buffer depth
-set=timer_legal_en = {0,1}
Internal timers legal/enabled
-set=bitmanip_zba = {0,1}
Bit manipulation extension ZBa enabled/legal
-set=bitmanip_zbb = {0,1}
Bit manipulation extension ZBb enabled/legal
-set=bitmanip_zbc = {0,1}
Bit manipulation extension ZBc enabled/legal
-set=bitmanip_zbe = {0,1}
Bit manipulation extension ZBe enabled/legal
-set=bitmanip_zbf = {0,1}
Bit manipulation extension ZBf enabled/legal
-set=bitmanip_zbp = {0,1}
Bit manipulation extension ZBp enabled/legal
-set=bitmanip_zbr = {0,1}
Bit manipulation extension ZBr enabled/legal
-set=bitmanip_zbs = {0,1}
Bit manipulation extension ZBs enabled/legal
-fpga_optimize = { 0, 1 }
if 1, minimize clock-gating to facilitate FPGA builds
-text_in_iccm = {0, 1}
Don't add ICCM preload code in generated link.ld
Additionally the following may be set for bus masters and slaves using the -set=var=value option:
{inst|data}_access_enable[0-7] : default 0
{inst|data}_access_addr[0-7] : default 0x00000000
{inst|data}_access_mask[0-7] : default 0xffffffff
";
my $ret_stack_size;
my $btb_size;
my $bht_size;
my $btb_fullya;
my $btb_toffset_size;
my $dccm_region;
my $dccm_offset;
my $dccm_size;
my $iccm_enable;
my $icache_enable;
my $icache_waypack;
my $icache_num_ways;
my $icache_banks_way;
my $icache_ln_sz;
my $icache_bank_width;
my $icache_ecc;
my $iccm_region;
my $iccm_offset;
my $iccm_size;
my $icache_size;
my $pic_2cycle;
my $pic_region;
my $pic_offset;
my $pic_size;
my $pic_total_int;
my $top_align_iccm = 0;
my $target = "default";
my $snapshot ;
my $build_path ;
my $verbose;
my $load_to_use_plus1;
my $btb_enable;
my $dccm_enable;
my $icache_2banks;
my $lsu_stbuf_depth;
my $dma_buf_depth;
my $lsu_num_nbload;
my $dccm_num_banks;
my $iccm_num_banks;
my $verilator;
my $icache_bypass_enable=1;
my $icache_num_bypass=2;
my $icache_num_bypass_width;
my $icache_tag_bypass_enable=1;
my $icache_tag_num_bypass=2;
my $icache_tag_num_bypass_width;
my $fast_interrupt_redirect = 1; # ON by default
my $lsu_num_nbload=4;
my $ahb = 0;
my $axi = 1;
my $text_in_iccm = 0;
my $lsu2dma = 0;
2022-03-08 17:18:19 +08:00
$ret_stack_size=4;
2022-03-07 21:08:10 +08:00
$btb_enable=1;
$btb_fullya=0;
$btb_toffset_size=12;
2022-03-08 17:18:19 +08:00
$btb_size=32;
$bht_size=128;
2022-03-07 21:08:10 +08:00
$dccm_enable=1;
$dccm_region="0xf";
$dccm_offset="0x40000"; #1*256*1024
2022-03-08 17:18:19 +08:00
$dccm_size=32;
$dccm_num_banks=8;
$iccm_enable=0;
2022-03-07 21:08:10 +08:00
$iccm_region="0xe";
$top_align_iccm = 1;
$iccm_offset="0xe000000"; #0x380*256*1024
2022-03-08 17:18:19 +08:00
$iccm_size=32;
$iccm_num_banks=8;
2022-03-07 21:08:10 +08:00
$icache_enable=1;
$icache_waypack=1;
$icache_num_ways=2;
$icache_banks_way=2;
$icache_2banks=1;
$icache_bank_width=8;
$icache_ln_sz=64;
2022-03-08 17:18:19 +08:00
$icache_ecc=0;
2022-03-07 21:08:10 +08:00
$icache_size=16;
$pic_2cycle=0;
$pic_region="0xf";
$pic_offset="0xc0000"; # 3*256*1024
$pic_size=32;
2022-03-08 17:18:19 +08:00
$pic_total_int=8;
2022-03-07 21:08:10 +08:00
$load_to_use_plus1=0;
$lsu_stbuf_depth=4;
$dma_buf_depth=5;
my $div_bit=4; # number of bits to process each cycle for div
my $div_new=1; # old or new div algorithm
my $fpga_optimize = 1;
# Default bitmanip options
my $bitmanip_zba = 1;
my $bitmanip_zbb = 1;
my $bitmanip_zbc = 1;
my $bitmanip_zbe = 0;
my $bitmanip_zbf = 0;
my $bitmanip_zbp = 0;
my $bitmanip_zbr = 0;
my $bitmanip_zbs = 1;
GetOptions(
"help" => \$help,
"target=s" => \$target,
"snapshot=s" => \$snapshot,
"verbose" => \$verbose,
"load_to_use_plus1" => \$load_to_use_plus1,
"ret_stack_size=s" => \$ret_stack_size,
"btb_fullya" => \$btb_fullya,
"btb_enable=s" => \$btb_enable,
"btb_size=s" => \$btb_size,
"bht_size=s" => \$bht_size,
"dccm_enable=s" => \$dccm_enable,
"dccm_region=s" => \$dccm_region,
"dccm_offset=s" => \$dccm_offset,
"dccm_size=s" => \$dccm_size,
"dma_buf_depth" => \$dma_buf_depth,
"iccm_enable=s" => \$iccm_enable,
"icache_enable=s" => \$icache_enable,
"icache_waypack=s" => \$icache_waypack,
"icache_num_ways=s" => \$icache_num_ways,
"icache_ln_sz=s" => \$icache_ln_sz,
"icache_ecc=s" => \$icache_ecc,
"icache_2banks=s" => \$icache_2banks,
"iccm_region=s" => \$iccm_region,
"iccm_offset=s" => \$iccm_offset,
"iccm_size=s" => \$iccm_size,
"lsu_stbuf_depth" => \$lsu_stbuf_depth,
"lsu_num_nbload" => \$lsu_num_nbload,
"pic_2cycle=s" => \$pic_2cycle,
"pic_region=s" => \$pic_region,
"pic_offset=s" => \$pic_offset,
"pic_size=s" => \$pic_size,
"pic_total_int=s" => \$pic_total_int,
"icache_size=s" => \$icache_size,
"set=s@" => \@sets,
"unset=s@" => \@unsets,
"fpga_optimize=s" => \$fpga_optimize,
"text_in_iccm" => \$text_in_iccm,
) || die("$helpusage");
if ($help) {
print "$helpusage\n";
exit;
}
if (!defined $snapshot ) {
$snapshot = $target;
}
if (!defined $ENV{BUILD_PATH}) {
$build_path = "$ENV{PWD}/snapshots/$snapshot" ;
} else {
$build_path = $ENV{BUILD_PATH};
}
if (! -d "$build_path") {
system ("mkdir -p $build_path");
}
# Parameter file
my $tdfile = "$build_path/el2_pdef.vh";
my $paramfile = "$build_path/el2_param.vh";
# Verilog defines file path
my $vlogfile = "$build_path/common_defines.vh";
# Assembly defines file path
my $asmfile = "$build_path/defines.h";
# PD defines file path
my $pdfile = "$build_path/pd_defines.vh";
# Whisper config file path
my $whisperfile = "$build_path/whisper.json";
#
# Default linker file
my $linkerfile = "$build_path/link.ld";
# Perl defines file path
my $perlfile = "$build_path/perl_configs.pl";
my $opensource=0;
# IDEA: is ghr at 5b the right size for el2 core
if ($target eq "default") { }
elsif ($target eq "lsu2dma_axi") {
$lsu2dma = 1;
$iccm_enable = 1;
}
elsif ($target eq "typical_pd") {
print "$self: Using target \"typical_pd\"\n";
$fpga_optimize = 0;
$ret_stack_size=2;
$btb_size=32;
$bht_size=128;
$dccm_size=16;
$dccm_num_banks=2;
$iccm_enable=0;
}
elsif ($target eq "high_perf") {
print "$self: Using target \"high_perf\"\n";
$btb_size=512;
$bht_size=2048;
}
elsif ($target eq "default_ahb") {
print "$self: Using target \"default_ahb\"\n";
$axi = 0;
$ahb = 1;
}
else {
die "$self: ERROR! Unsupported target \"$target\". Supported are 'default', 'default_ahb', 'typical_pd', 'high_perf', 'lsu2dma_axi\n" ;
}
# Configure triggers
our @triggers = (#{{{
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
"mask" => ["0x081818c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081818c7", "0xffffffff", "0x00000000"]
},
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
"mask" => ["0x081810c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081810c7", "0xffffffff", "0x00000000"]
},
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
"mask" => ["0x081818c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081818c7", "0xffffffff", "0x00000000"]
},
{
"reset" => ["0x23e00000", "0x00000000", "0x00000000"],
"mask" => ["0x081810c7", "0xffffffff", "0x00000000"],
"poke_mask" => ["0x081810c7", "0xffffffff", "0x00000000"]
},
);#}}}
# Configure CSRs
our %csr = (#{{{
"mstatus" => {
"reset" => "0x1800", # MPP bits hard wired to binrary 11.
"mask" => "0x88", # Only mpie(7) & mie(3) bits writeable
"exists" => "true",
},
"mie" => {
"reset" => "0x0",
# Only external, timer, local, and software writeable
"mask" => "0x70000888",
"exists" => "true",
},
"mip" => {
"reset" => "0x0",
# None of the bits are writeable using CSR instructions
"mask" => "0x0",
# Bits corresponding to error overflow, external, timer and stoftware
# interrupts are modifiable
"poke_mask" => "0x70000888",
"exists" => "true",
},
"mcountinhibit" => {
"commnet" => "Performance counter inhibit. One bit per counter.",
"reset" => "0x0",
"mask" => "0x7d",
"poke_mask" => "0x7d",
"exists" => "true",
},
"mcounteren" => {
"exists" => "false",
},
"mvendorid" => {
"reset" => "0x45",
"mask" => "0x0",
"exists" => "true",
},
"marchid" => {
"reset" => "0x00000010",
"mask" => "0x0",
"exists" => "true",
},
"mimpid" => {
"reset" => "0x4",
"mask" => "0x0",
"exists" => "true",
},
"misa" => {
"reset" => "0x40001104",
"mask" => "0x0",
"exists" => "true",
},
"tselect" => {
"reset" => "0x0",
"mask" => "0x3", # Four triggers
"exists" => "true",
},
"mhartid" => {
"reset" => "0x0",
"mask" => "0x0",
"poke_mask" => "0xfffffff0",
"exists" => "true",
},
"dcsr" => {
"reset" => "0x40000003",
"mask" => "0x00008c04",
"poke_mask" => "0x00008dcc", # cause field modifiable, nmip modifiable
"exists" => "true",
"debug" => "true",
},
"cycle" => {
"exists" => "false",
},
"time" => {
"exists" => "false",
},
"instret" => {
"exists" => "false",
},
"mhpmcounter3" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter4" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter5" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter6" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter3h" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter4h" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter5h" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmcounter6h" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmevent3" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmevent4" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmevent5" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mhpmevent6" => {
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
# Remaining CSRs are non-standard. These are specific to SWERV
"dicawics" => {
"number" => "0x7c8",
"reset" => "0x0",
"mask" => "0x0130fffc",
"exists" => "true",
},
"dicad0" => {
"number" => "0x7c9",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"dicad1" => {
"number" => "0x7ca",
"reset" => "0x0",
"mask" => "0x3",
"exists" => "true",
},
"dicago" => {
"number" => "0x7cb",
"reset" => "0x0",
"mask" => "0x0",
"exists" => "true",
},
"mitcnt0" => {
"number" => "0x7d2",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mitbnd0" => {
"number" => "0x7d3",
"reset" => "0xffffffff",
"mask" => "0xffffffff",
"exists" => "true",
},
"mitctl0" => {
"number" => "0x7d4",
"reset" => "0x1",
"mask" => "0x00000007",
"exists" => "true",
},
"mitcnt1" => {
"number" => "0x7d5",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mitbnd1" => {
"number" => "0x7d6",
"reset" => "0xffffffff",
"mask" => "0xffffffff",
"exists" => "true",
},
"mitctl1" => {
"number" => "0x7d7",
"reset" => "0x1",
"mask" => "0x0000000f",
"exists" => "true",
},
"mcpc" => {
"comment" => "Core pause",
"number" => "0x7c2",
"reset" => "0x0",
"mask" => "0x0",
"exists" => "true",
},
"mpmc" => {
"number" => "0x7c6",
"reset" => "0x2",
"mask" => "0x2",
"exists" => "true",
},
"micect" => {
"number" => "0x7f0",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"miccmect" => {
"number" => "0x7f1",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mdccmect" => {
"number" => "0x7f2",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
},
"mcgc" => {
"number" => "0x7f8",
"reset" => "0x200",
"mask" => "0x000003ff",
"poke_mask" => "0x000003ff",
"exists" => "true",
},
"mfdc" => {
"number" => "0x7f9",
"reset" => "0x00070000",
"mask" => "0x00071fff",
"exists" => "true",
},
"mrac" => {
"comment" => "Memory region io and cache control.",
"number" => "0x7c0",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
"shared" => "true",
},
"dmst" => {
"comment" => "Memory synch trigger: Flush caches in debug mode.",
"number" => "0x7c4",
"reset" => "0x0",
"mask" => "0x0",
"exists" => "true",
"debug" => "true",
},
"dicawics" => {
"comment" => "Cache diagnostics.",
"number" => "0x7c8",
"reset" => "0x0",
"mask" => "0x0130fffc",
"exists" => "true",
"debug" => "true",
},
"dicad0" => {
"comment" => "Cache diagnostics.",
"number" => "0x7c9",
"reset" => "0x0",
"mask" => "0xffffffff",
"exists" => "true",
"debug" => "true",
},
"dicad1" => {
"comment" => "Cache diagnostics.",
"number" => "0x7ca",
"reset" => "0x0",
"mask" => "0x3",
"exists" => "true",
"debug" => "true",
},
"dicago" => {
"comment" => "Cache diagnostics.",
"number" => "0x7cb",
"reset" => "0x0",
"mask" => "0x0",
"exists" => "true",
"debug" => "true",
},
"meipt" => {
"comment" => "External interrupt priority threshold.",
"number" => "0xbc9",
"reset" => "0x0",
"mask" => "0xf",
"exists" => "true",
},
"meicpct" => {
"comment" => "External claim id/priority capture.",
"number" => "0xbca",
"reset" => "0x0",
"mask" => "0x0",
"exists" => "true",
},
"meicidpl" => {
"comment" => "External interrupt claim id priority level.",
"number" => "0xbcb",
"reset" => "0x0",
"mask" => "0xf",
"exists" => "true",
},
"meicurpl" => {
"comment" => "External interrupt current priority level.",
"number" => "0xbcc",
"reset" => "0x0",
"mask" => "0xf",
"exists" => "true",
},
"mfdht" => {
"comment" => "Force Debug Halt Threshold",
"number" => "0x7ce",
"reset" => "0x0",
"mask" => "0x0000003f",
"exists" => "true",
"shared" => "true",
},
"mfdhs" => {
"comment" => "Force Debug Halt Status",
"number" => "0x7cf",
"reset" => "0x0",
"mask" => "0x00000003",
"exists" => "true",
},
"mscause" => {
"number" => "0x7ff",
"reset" => "0x0",
"mask" => "0x0000000f",
"exists" => "true",
},
);#}}}
# These are the peformance counters events implemented for el2s. An
# event number from outside this list will be replaced by zero if
# written to an MHPMEVENT CSR.
my @perf_events = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30,
31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 54, 55, 56,
512, 513, 514, 515, 516);
foreach my $i (0 .. 3) {
$csr{"pmpcfg$i"} = { "exists" => "false" };
}
foreach my $i (0 .. 15) {
$csr{"pmpaddr$i"} = { "exists" => "false" };
}
# }}}
# Main config hash, with default values
#
# Hash can be hierarchical with arbitrary levels
# Hexadecimal values are prefixed with 0x
#
# For verilog, if bit width is expected, add to %width hash below
#
# NOTE: params/keys marked 'derived' are not settable via cmd line, unless they ALSO have the 'overridable' tag
#
our %config = (#{{{
"harts" => "1",
"xlen" => "32", # Testbench, Do Not Override
"numiregs" => "32", # Testbench, Do Not Override
"regwidth" => "32", # Testbench, Do Not Override
"reset_vec" => "0x80000000", # Testbench, Overridable
"nmi_vec" => "0x11110000", # Testbench, Overridable
"physical" => "1",
"num_mmode_perf_regs" => "4", # Whisper only
"max_mmode_perf_event" => "516", # Whisper only: performance counters event ids will be clamped to this
"target" => $target, # Flow Infrastructure
"config_key" => "derived",
"tec_rv_icg" => "clockhdr",
"retstack" => {
"ret_stack_size" => "$ret_stack_size", # Design Parm, Overridable
},
"btb" => {
"btb_enable" => "$btb_enable", # Design Parm, Overridable
"btb_fullya" => "$btb_fullya", # Design Parm, Overridable
"btb_toffset_size" => "$btb_toffset_size", # Constant
"btb_size" => "$btb_size", # Design Parm, Overridable
"btb_index1_hi" => "derived",
"btb_index1_lo" => "2", # Constant, Do Not Override
"btb_index2_hi" => "derived",
"btb_index2_lo" => "derived",
"btb_index3_hi" => "derived",
"btb_index3_lo" => "derived",
"btb_addr_hi" => "derived",
"btb_array_depth" => "derived",
"btb_addr_lo" => "2", # Constant, Do Not Override
"btb_btag_size" => "derived",
"btb_btag_fold" => "derived",
"btb_fold2_index_hash" => "derived",
},
"bht" => {
"bht_size" => "$bht_size", # Design Parm, Overridable
"bht_addr_hi" => "derived",
"bht_addr_lo" => "2", # Constant, Do Not Override
"bht_array_depth" => "derived",
"bht_ghr_size" => "derived",
"bht_ghr_range" => "derived",
"bht_hash_string" => "derived",
"bht_ghr_hash_1" => "derived",
},
"core" => {
"div_bit" => "$div_bit", # Design Parm, Overridable
"div_new" => "$div_new", # Design Parm, Overridable
"lsu_stbuf_depth" => "$lsu_stbuf_depth", # Design Parm, Overridable
"dma_buf_depth" => "$dma_buf_depth", # Design Parm, Overridable
"lsu_num_nbload" => "$lsu_num_nbload", # Design Parm, Overridable
"opensource" => "$opensource", # Flow Infrastructure
"verilator" => "$verilator", # Flow Infrastructure
"load_to_use_plus1" => "$load_to_use_plus1", # Design Parm, Overridable
"iccm_icache" => 'derived', # Used by design
"iccm_only" => 'derived', # Used by design
"icache_only" => 'derived', # Used by design
"no_iccm_no_icache" => 'derived', # Used by design
"timer_legal_en" => '1', # Design Parm, Overridable
"bitmanip_zba" => $bitmanip_zba, # Design Parm, Overridable
"bitmanip_zbb" => $bitmanip_zbb, # Design Parm, Overridable
"bitmanip_zbc" => $bitmanip_zbc, # Design Parm, Overridable
"bitmanip_zbe" => $bitmanip_zbe, # Design Parm, Overridable
"bitmanip_zbf" => $bitmanip_zbf, # Design Parm, Overridable
"bitmanip_zbp" => $bitmanip_zbp, # Design Parm, Overridable
"bitmanip_zbr" => $bitmanip_zbr, # Design Parm, Overridable
"bitmanip_zbs" => $bitmanip_zbs, # Design Parm, Overridable
"fast_interrupt_redirect" => "$fast_interrupt_redirect", # Design Parm, Overridable
"lsu2dma" => $lsu2dma, # used by design/TB for LSU to DMA bridge
"fpga_optimize" => $fpga_optimize # Design Parm, Overridable
},
"dccm" => {
"dccm_enable" => "$dccm_enable", # Design Parm, Overridable
"dccm_region" => "$dccm_region", # Design Parm, Overridable
"dccm_offset" => "$dccm_offset", # Design Parm, Overridable
"dccm_size" => "$dccm_size", # Design Parm, Overridable
"dccm_num_banks" => "$dccm_num_banks", # Design Parm, Overridable
"dccm_sadr" => 'derived',
"dccm_eadr" => 'derived',
"dccm_bits" => 'derived',
"dccm_bank_bits" => 'derived',
"dccm_data_width" => 'derived',
"dccm_fdata_width" => 'derived',
"dccm_byte_width" => 'derived',
"dccm_width_bits" => 'derived',
"dccm_index_bits" => 'derived',
"dccm_ecc_width" => 'derived',
"lsu_sb_bits" => 'derived',
"dccm_data_cell" => 'derived',
"dccm_rows" => 'derived',
"dccm_reserved" => 'derived', # Testbench use only : reserve dccm space for SW/stack - no random r/w
},
"iccm" => {
"iccm_enable" => "$iccm_enable", # Design Parm, Overridable
"iccm_region" => "$iccm_region", # Design Parm, Overridable
"iccm_offset" => "$iccm_offset", # Design Parm, Overridable
"iccm_size" => "$iccm_size", # Design Parm, Overridable
"iccm_num_banks" => "$iccm_num_banks", # Design Parm, Overridable
"iccm_bank_bits" => 'derived',
"iccm_index_bits" => 'derived',
"iccm_rows" => 'derived',
"iccm_data_cell" => 'derived',
"iccm_sadr" => 'derived',
"iccm_eadr" => 'derived',
"iccm_reserved" => 'derived', # Testbench use only : reserve iccm space for SW/handlers - no random r/w
"iccm_bank_hi" => 'derived',
"iccm_bank_index_lo" => 'derived',
},
"icache" => {
"icache_enable" => "$icache_enable", # Design Parm, Overridable
"icache_waypack" => "$icache_waypack", # Design Parm, Overridable
"icache_num_ways" => "$icache_num_ways", # Design Parm, Overridable
"icache_banks_way" => "2", # Design Parm, Constant
"icache_bank_width" => "8", # Design Parm, Constant
"icache_ln_sz" => "$icache_ln_sz", # Design Parm, Overridable
"icache_size" => "$icache_size", # Design Parm, Overridable
"icache_bypass_enable" => "$icache_bypass_enable", # Design Parm, Overridable
"icache_num_bypass" => "$icache_num_bypass", # Design Parm, Overridable
"icache_num_bypass_width" => 'derived',
"icache_tag_bypass_enable" => "$icache_tag_bypass_enable", # Design Parm, Overridable
"icache_tag_num_bypass" => "$icache_tag_num_bypass", # Design Parm, Overridable
"icache_tag_num_bypass_width" => 'derived',
"icache_bank_hi" => 'derived',
"icache_bank_lo" => 'derived',
"icache_data_cell" => 'derived',
"icache_tag_cell" => 'derived',
"icache_tag_depth" => 'derived',
"icache_data_depth" => 'derived',
"icache_num_lines" => 'derived',
"icache_num_lines_bank" => 'derived',
"icache_num_lines_way" => 'derived',
"icache_data_depth" => 'derived',
"icache_tag_lo" => 'derived',
"icache_index_hi" => 'derived',
"icache_data_index_lo" => 'derived',
"icache_data_width" => 'derived',
"icache_fdata_width" => 'derived',
"icache_tag_index_lo" => 'derived',
"icache_ecc" => "$icache_ecc", # Design Parm, Overridable
"icache_2banks" => "$icache_2banks", # Design Parm, Overridable
"icache_bank_bits" => "derived",
"icache_status_bits" => "derived",
"icache_num_beats" => "derived",
"icache_beat_bits" => "derived",
"icache_scnd_last" => "derived",
"icache_beat_addr_hi" => "derived",
},
"pic" => {
"pic_2cycle" => "$pic_2cycle", # Design Parm, Overridable
"pic_region" => "$pic_region", # Design Parm, Overridable
"pic_offset" => "$pic_offset", # Design Parm, Overridable
"pic_size" => "$pic_size", # Design Parm, Overridable
"pic_base_addr" => 'derived',
"pic_total_int_plus1" => 'derived', # pic_total_int + 1
"pic_total_int" => "$pic_total_int", # Design Parm, Overridable
"pic_int_words" => 'derived', # number of 32 bit words for packed registers (Xmax)
"pic_bits" => 'derived', # of bits needs to address the PICM
"pic_meipl_offset" => '0x0000', # Testbench only: Offset of meipl relative to pic_base_addr
"pic_meip_offset" => '0x1000', # Testbench only: Offset of meip relative to pic_base_addr
"pic_meie_offset" => '0x2000', # Testbench only: Offset of meie relative to pic_base_addr
"pic_mpiccfg_offset" => '0x3000', # Testbench only: Offset of mpiccfg relative to pic_base_addr
"pic_meipt_offset" => '0x3004', # Testbench only: Offset of meipt relative to pic_base_addr -- deprecated
"pic_meigwctrl_offset" => '0x4000', # Testbench only: gateway control regs relative to pic_base_addr
"pic_meigwclr_offset" => '0x5000', # Testbench only: gateway clear regs relative to pic_base_addr
"pic_meipl_mask" => '0xf', # Whisper only
"pic_meip_mask" => '0x0',
"pic_meie_mask" => '0x1',
"pic_mpiccfg_mask" => '0x1',
"pic_meipt_mask" => '0x0',
"pic_meigwctrl_mask" => '0x3',
"pic_meigwclr_mask" => '0x0',
"pic_meipl_count" => 'derived',
"pic_meip_count" => 'derived',
"pic_meie_count" => 'derived',
"pic_mpiccfg_count" => 1,
"pic_meipt_count" => 'derived',
"pic_meigwctrl_count" => 'derived',
"pic_meigwclr_count" => 'derived',
},
"testbench" => { # Testbench only
"TOP" => "tb_top",
"RV_TOP" => "`TOP.rvtop",
"CPU_TOP" => "`RV_TOP.swerv",
"clock_period" => "100",
"build_ahb_lite" => "$ahb",
"build_axi4" => "$axi",
"build_axi_native" => "1",
"assert_on" => "",
"ext_datawidth" => "64",
"ext_addrwidth" => "32",
"sterr_rollback" => "0",
"lderr_rollback" => "1",
"SDVT_AHB" => "$ahb",
},
"protection" => { # Design parms, Overridable - static MPU
"inst_access_enable0" => "0x0",
"inst_access_addr0" => "0x00000000",
"inst_access_mask0" => "0xffffffff",
"inst_access_enable1" => "0x0",
"inst_access_addr1" => "0x00000000",
"inst_access_mask1" => "0xffffffff",
"inst_access_enable2" => "0x0",
"inst_access_addr2" => "0x00000000",
"inst_access_mask2" => "0xffffffff",
"inst_access_enable3" => "0x0",
"inst_access_addr3" => "0x00000000",
"inst_access_mask3" => "0xffffffff",
"inst_access_enable4" => "0x0",
"inst_access_addr4" => "0x00000000",
"inst_access_mask4" => "0xffffffff",
"inst_access_enable5" => "0x0",
"inst_access_addr5" => "0x00000000",
"inst_access_mask5" => "0xffffffff",
"inst_access_enable6" => "0x0",
"inst_access_addr6" => "0x00000000",
"inst_access_mask6" => "0xffffffff",
"inst_access_enable7" => "0x0",
"inst_access_addr7" => "0x00000000",
"inst_access_mask7" => "0xffffffff",
"data_access_enable0" => "0x0",
"data_access_addr0" => "0x00000000",
"data_access_mask0" => "0xffffffff",
"data_access_enable1" => "0x0",
"data_access_addr1" => "0x00000000",
"data_access_mask1" => "0xffffffff",
"data_access_enable2" => "0x0",
"data_access_addr2" => "0x00000000",
"data_access_mask2" => "0xffffffff",
"data_access_enable3" => "0x0",
"data_access_addr3" => "0x00000000",
"data_access_mask3" => "0xffffffff",
"data_access_enable4" => "0x0",
"data_access_addr4" => "0x00000000",
"data_access_mask4" => "0xffffffff",
"data_access_enable5" => "0x0",
"data_access_addr5" => "0x00000000",
"data_access_mask5" => "0xffffffff",
"data_access_enable6" => "0x0",
"data_access_addr6" => "0x00000000",
"data_access_mask6" => "0xffffffff",
"data_access_enable7" => "0x0",
"data_access_addr7" => "0x00000000",
"data_access_mask7" => "0xffffffff",
},
"memmap" => { # Testbench only
"serialio" => 'derived, overridable', # Testbench only
"external_data" => 'derived, overridable', # Testbench only
"debug_sb_mem" => 'derived, overridable', # Testbench only
"external_data_1" => 'derived, overridable', # Testbench only
"external_mem_hole" => 'default disabled', # Testbench only
# "consoleio" => 'derived', # Part of serial io.
},
"bus" => {
"lsu_bus_tag" => 'derived',
"lsu_bus_id" => '1',
"lsu_bus_prty" => '2',
"dma_bus_tag" => '1',
"dma_bus_id" => '1',
"dma_bus_prty" => '2',
"sb_bus_tag" => '1',
"sb_bus_id" => '1',
"sb_bus_prty" => '2',
"ifu_bus_tag" => 'derived',
"ifu_bus_id" => '1',
"ifu_bus_prty" => '2',
"bus_prty_default" => '3',
},
"triggers" => \@triggers, # Whisper only
"csr" => \%csr, # Whisper only
"perf_events" => \@perf_events, # Whisper only
"even_odd_trigger_chains" => "true", # Whisper only
);
# These parms are used in the Verilog and will be part of global parm structure
# need to have this be width in binary
# for now autosize to the data
our %verilog_parms = (
"lsu2dma" => '1',
"timer_legal_en" => '1',
"bitmanip_zbb" => '1',
"bitmanip_zbs" => '1',
"bitmanip_zba" => '1',
"bitmanip_zbc" => '1',
"bitmanip_zbe" => '1',
"bitmanip_zbf" => '1',
"bitmanip_zbp" => '1',
"bitmanip_zbr" => '1',
"fast_interrupt_redirect" => '1',
"inst_access_enable0" => '1',
"inst_access_addr0" => '32',
"inst_access_mask0" => '32',
"inst_access_enable1" => '1',
"inst_access_addr1" => '32',
"inst_access_mask1" => '32',
"inst_access_enable2" => '1',
"inst_access_addr2" => '32',
"inst_access_mask2" => '32',
"inst_access_enable3" => '1',
"inst_access_addr3" => '32',
"inst_access_mask3" => '32',
"inst_access_enable4" => '1',
"inst_access_addr4" => '32',
"inst_access_mask4" => '32',
"inst_access_enable5" => '1',
"inst_access_addr5" => '32',
"inst_access_mask5" => '32',
"inst_access_enable6" => '1',
"inst_access_addr6" => '32',
"inst_access_mask6" => '32',
"inst_access_enable7" => '1',
"inst_access_addr7" => '32',
"inst_access_mask7" => '32',
"data_access_enable0" => '1',
"data_access_addr0" => '32',
"data_access_mask0" => '32',
"data_access_enable1" => '1',
"data_access_addr1" => '32',
"data_access_mask1" => '32',
"data_access_enable2" => '1',
"data_access_addr2" => '32',
"data_access_mask2" => '32',
"data_access_enable3" => '1',
"data_access_addr3" => '32',
"data_access_mask3" => '32',
"data_access_enable4" => '1',
"data_access_addr4" => '32',
"data_access_mask4" => '32',
"data_access_enable5" => '1',
"data_access_addr5" => '32',
"data_access_mask5" => '32',
"data_access_enable6" => '1',
"data_access_addr6" => '32',
"data_access_mask6" => '32',
"data_access_enable7" => '1',
"data_access_addr7" => '32',
"data_access_mask7" => '32',
"iccm_bits" => '5',
"iccm_bank_hi" => '5',
"iccm_bank_index_lo" => '5',
"icache_bank_bits" => '3',
"icache_status_bits" => '3',
"icache_num_beats" => '4',
"icache_beat_bits" => '4',
"icache_scnd_last" => '4',
"icache_beat_addr_hi" => '4',
"icache_bypass_enable" => '1',
"icache_num_bypass" => '4',
"icache_num_bypass_width" => '4',
"icache_tag_bypass_enable" => '1',
"icache_tag_num_bypass" => '4',
"icache_tag_num_bypass_width" => '4',
"iccm_icache" => '1',
"iccm_only" => '1',
"icache_only" => '1',
"no_iccm_no_icache" => '1',
"build_axi4" => '1',
"build_ahb_lite" => '1',
"build_axi_native" => '1',
"lsu_num_nbload_width" => '3',
"lsu_num_nbload" => '5',
"ret_stack_size" => '4',
"btb_fullya" => '1',
"btb_toffset_size" => '5',
"btb_enable" => '1',
"btb_size" => '10',
"btb_index1_hi" => '5',
"btb_index1_lo" => '5',
"btb_index2_hi" => '5',
"btb_index2_lo" => '5',
"btb_index3_hi" => '5',
"btb_index3_lo" => '5',
"btb_addr_hi" => '5',
"btb_array_depth" => '9',
"btb_addr_lo" => '2',
"btb_btag_size" => '5',
"btb_btag_fold" => '1',
"btb_fold2_index_hash" => '1',
"bht_size" => '12',
"bht_addr_hi" => '4',
"bht_addr_lo" => '2',
"bht_array_depth" => '11',
"bht_ghr_size" => '4',
"bht_ghr_hash_1" => '1',
"div_bit" => '3',
"div_new" => '1',
"lsu_stbuf_depth" => '4',
"dma_buf_depth" => '3',
"load_to_use_plus1" => '1',
"dccm_enable" => '1',
"dccm_region" => '4',
"dccm_size" => '10',
"dccm_num_banks" => '5',
"dccm_sadr" => '32',
"dccm_bits" => '5',
"dccm_bank_bits" => '3',
"dccm_data_width" => '6',
"dccm_fdata_width" => '6',
"dccm_byte_width" => '3',
"dccm_width_bits" => '2',
"dccm_index_bits" => '4',
"dccm_ecc_width" => '3',
"lsu_sb_bits" => '5',
"iccm_enable" => '1',
"iccm_region" => '4',
"iccm_size" => '10',
"iccm_num_banks" => '5',
"iccm_bank_bits" => '3',
"iccm_index_bits" => '4',
"iccm_sadr" => '32',
"icache_enable" => '1',
"icache_waypack" => '1',
"icache_num_ways" => '3',
"icache_banks_way" => '3',
"icache_bank_width" => '4',
"icache_ln_sz" => '7',
"icache_size" => '9',
"icache_bank_hi" => '3',
"icache_bank_lo" => '2',
"icache_tag_depth" => '13',
"icache_data_depth" => '14',
"icache_tag_lo" => '5',
"icache_index_hi" => '5',
"icache_data_index_lo" => '3',
"icache_data_width" => '7',
"icache_fdata_width" => '7',
"icache_tag_index_lo" => '3',
"icache_ecc" => '1',
"icache_2banks" => '1',
"pic_2cycle" => '1',
"pic_region" => '4',
"pic_size" => '9',
"pic_base_addr" => '32',
"pic_total_int_plus1" => '9',
"pic_total_int" => '8',
"pic_int_words" => '4',
"pic_bits" => '5',
"lsu_bus_tag" => '4',
"lsu_bus_id" => '1',
"lsu_bus_prty" => '2',
"dma_bus_tag" => '4',
"dma_bus_id" => '5',
"dma_bus_prty" => '2',
"sb_bus_tag" => '4',
"sb_bus_id" => '1',
"sb_bus_prty" => '2',
"ifu_bus_tag" => '4',
"ifu_bus_id" => '1',
"ifu_bus_prty" => '2',
"bus_prty_default" => '2',
);
# to make sure parameter math works properly add 4 to each key of %verilog_parms - was an issue in btb calculations
my $key;
foreach $key (keys %verilog_parms) {
$verilog_parms{$key} += 4;
}
# need to figure out what to do here
# for now none of these can be parameters
# move deletes lower
# Perform any overrides first before derived values
#
map_set_unset();
gen_define("","", \%config,"",[]);
# perform final checks
my $c;
$c=$config{retstack}{ret_stack_size}; if (!($c >=2 && $c <=8)) { die("$helpusage\n\nFAIL: ret_stack_size == $c; ILLEGAL !!!\n\n"); }
$c=$config{btb}{btb_size}; if (!($c==8||$c==16||$c==32||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: btb_size == $c; ILLEGAL !!!\n\n"); }
$c=$config{btb}{btb_size}; if (($c==64||$c==128||$c==256||$c==512) && $config{btb}{btb_fullya}) { die("$helpusage\n\nFAIL: btb_size == $c; btb_fullya=1 ILLEGAL !!!\n\n"); }
$c=$config{iccm}{iccm_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: iccm_region == $c ILLEGAL !!!\n\n"); }
$c=$config{iccm}{iccm_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: iccm_offset == $c ILLEGAL !!!\n\n"); }
$c=$config{iccm}{iccm_size}; if (!($c==2||$c==4||$c==8||$c==16||$c==32||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: iccm_size == $c ILLEGAL !!!\n\n"); }
$c=$config{iccm}{iccm_num_banks}; if (!($c==2 || $c==4 || ($c==8 && $config{iccm}{iccm_size} != 2) || ($c==16 && $config{iccm}{iccm_size} > 4))) { die("$helpusage\n\nFAIL: iccm_num_banks == $c ILLEGAL !!!\n\n"); }
$c=$config{iccm}{iccm_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: iccm_enable == $c ILLEGAL !!!\n\n"); }
$c=$config{dccm}{dccm_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: dccm_region == $c ILLEGAL !!!\n\n"); }
$c=$config{dccm}{dccm_num_banks}; if (!(($c==2 && $config{dccm}{dccm_size} != 48) || $c==4 || ($c==8 && $config{dccm}{dccm_size} != 48) || ($c==16 && $config{dccm}{dccm_size} != 4 && $config{dccm}{dccm_size} != 48)))
{ die("$helpusage\n\nFAIL: dccm_num_banks == $c ILLEGAL !!!\n\n"); }
$c=$config{dccm}{dccm_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: dccm_offset == $c ILLEGAL !!!\n\n"); }
$c=$config{dccm}{dccm_size}; if (!($c==4||$c==8||$c==16||$c==32||$c==48||$c==64||$c==128||$c==256||$c==512)) { die("$helpusage\n\nFAIL: dccm_size == $c ILLEGAL !!!\n\n"); }
$c=$config{pic}{pic_2cycle}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: pic_2cycle == $c ILLEGAL !!!\n\n"); }
$c=$config{pic}{pic_region}; if (!($c>=0 && $c<16)) { die("$helpusage\n\nFAIL: pic_region == $c ILLEGAL !!!\n\n"); }
$c=$config{pic}{pic_offset}; if (!($c>=0 && $c<256*1024*1024 && ($c&0xfff)==0)) { die("$helpusage\n\nFAIL: pic_offset == $c ILLEGAL !!!\n\n"); }
$c=$config{pic}{pic_size}; if (!($c==32 || $c==64 || $c==128 || $c==256)) { die("$helpusage\n\nFAIL: pic_size == $c ILLEGAL !!!\n\n"); }
$c=$config{pic}{pic_total_int}; if ( $c<1 || $c>255) { die("$helpusage\n\nFAIL: pic_total_int == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_num_bypass}; if ($c<1 || $c>8) { die("$helpusage\n\nFAIL: icache_num_bypass == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_bypass_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_bypass_enable == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_tag_num_bypass}; if ($c<1 || $c>8) { die("$helpusage\n\nFAIL: icache_tag_num_bypass == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_tag_bypass_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_tag_bypass_enable == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_enable}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_enable == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_waypack}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: icache_waypack == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_num_ways}; if (!($c==2 || $c==4)) { die("$helpusage\n\nFAIL: icache_num_ways == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_ln_sz}; if (!($c==32 || $c==64)) { die("$helpusage\n\nFAIL: icache_ln_sz == $c ILLEGAL !!!\n\n"); }
$c=$config{icache}{icache_size}; if (!($c==8 || $c==16 || $c==32 || $c==64 || $c==128 || $c==256)) { die("$helpusage\n\nFAIL: icache_size == $c ILLEGAL !!!\n\n"); }
$c=$config{core}{div_bit}; if (!($c==1 || $c==2 || $c==3 || $c==4 )) { die("$helpusage\n\nFAIL: div_bit == $c ILLEGAL !!!\n\n"); }
$c=$config{core}{div_new}; if (!($c==0 || $c==1)) { die("$helpusage\n\nFAIL: div_new == $c ILLEGAL !!!\n\n"); }
$c=$config{core}{lsu_stbuf_depth}; if (!($c==2 || $c==4 || $c==8)) { die("$helpusage\n\nFAIL: lsu_stbuf_depth == $c ILLEGAL !!!\n\n"); }
$c=$config{core}{dma_buf_depth}; if (!($c==2 || $c==4 || $c==5)) { die("$helpusage\n\nFAIL: dma_buf_depth == $c ILLEGAL !!!\n\n"); }
$c=$config{core}{lsu_num_nbload}; if (!($c==2 || $c==4 || $c==8)) { die("$helpusage\n\nFAIL: lsu_num_nbload == $c ILLEGAL !!!\n\n"); }
# force div_bit to be 1 for old div algorithm
if ($config{core}{div_new}==0 && $config{core}{div_bit}!=1) {
die("$helpusage\n\nFAIL: div_new=0 requires div_bit=1 ILLEGAL !!!\n\n");
}
$c=$config{protection}{inst_access_addr0}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr0 lower 6b must be 0s $c !!!\n\n"); }
$c=$config{protection}{inst_access_addr1}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr1 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr2}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr2 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr3}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr3 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr4}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr4 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr5}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr5 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr6}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr6 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_addr7}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: inst_access_addr7 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{inst_access_mask0}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask0 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask1}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask1 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask2}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask2 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask3}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask3 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask4}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask4 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask5}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask5 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask6}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask6 invalid !!!\n\n"); }
$c=$config{protection}{inst_access_mask7}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: inst_access_mask7 invalid !!!\n\n"); }
$c=$config{protection}{data_access_addr0}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr0 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr1}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr1 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr2}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr2 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr3}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr3 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr4}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr4 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr5}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr5 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr6}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr6 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_addr7}; if ((hex($c)&0x3f) != 0) { die("$helpusage\n\nFAIL: data_access_addr7 lower 6b must be 0s !!!\n\n"); }
$c=$config{protection}{data_access_mask0}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask0 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask1}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask1 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask2}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask2 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask3}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask3 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask4}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask4 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask5}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask5 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask6}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask6 invalid !!!\n\n"); }
$c=$config{protection}{data_access_mask7}; if ((hex($c)&0x3f) != 63 || invalid_mask($c)) { die("$helpusage\n\nFAIL: data_access_mask7 invalid !!!\n\n"); }
if ((hex($config{protection}{inst_access_addr0}) & hex($config{protection}{inst_access_mask0}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr0 and inst_access_mask0 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr1}) & hex($config{protection}{inst_access_mask1}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr1 and inst_access_mask1 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr2}) & hex($config{protection}{inst_access_mask2}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr2 and inst_access_mask2 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr3}) & hex($config{protection}{inst_access_mask3}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr3 and inst_access_mask3 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr4}) & hex($config{protection}{inst_access_mask4}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr4 and inst_access_mask4 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr5}) & hex($config{protection}{inst_access_mask5}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr5 and inst_access_mask5 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr6}) & hex($config{protection}{inst_access_mask6}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr6 and inst_access_mask6 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{inst_access_addr7}) & hex($config{protection}{inst_access_mask7}))!=0) { die("$helpusage\n\nFAIL: inst_access_addr7 and inst_access_mask7 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr0}) & hex($config{protection}{data_access_mask0}))!=0) { die("$helpusage\n\nFAIL: data_access_addr0 and data_access_mask0 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr1}) & hex($config{protection}{data_access_mask1}))!=0) { die("$helpusage\n\nFAIL: data_access_addr1 and data_access_mask1 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr2}) & hex($config{protection}{data_access_mask2}))!=0) { die("$helpusage\n\nFAIL: data_access_addr2 and data_access_mask2 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr3}) & hex($config{protection}{data_access_mask3}))!=0) { die("$helpusage\n\nFAIL: data_access_addr3 and data_access_mask3 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr4}) & hex($config{protection}{data_access_mask4}))!=0) { die("$helpusage\n\nFAIL: data_access_addr4 and data_access_mask4 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr5}) & hex($config{protection}{data_access_mask5}))!=0) { die("$helpusage\n\nFAIL: data_access_addr5 and data_access_mask5 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr6}) & hex($config{protection}{data_access_mask6}))!=0) { die("$helpusage\n\nFAIL: data_access_addr6 and data_access_mask6 must be orthogonal!!!\n\n"); }
if ((hex($config{protection}{data_access_addr7}) & hex($config{protection}{data_access_mask7}))!=0) { die("$helpusage\n\nFAIL: data_access_addr7 and data_access_mask7 must be orthogonal!!!\n\n"); }
# Fill in derived configuration entries.
if (($config{icache}{icache_enable}==0 || grep(/icache_enable/, @unsets)) && $config{iccm}{iccm_enable}==0) {
$config{core}{no_iccm_no_icache}=1;
}
elsif (($config{icache}{icache_enable}==0 || grep(/icache_enable/, @unsets)) && $config{iccm}{iccm_enable}==1) {
$config{core}{iccm_only}=1;
}
elsif ($config{icache}{icache_enable}==1 && $config{iccm}{iccm_enable}==0) {
$config{core}{icache_only}=1;
}
elsif ($config{icache}{icache_enable}==1 && $config{iccm}{iccm_enable}==1) {
$config{core}{iccm_icache}=1;
}
if (!$config{dccm}{dccm_enable}) {
$config{core}{fast_interrupt_redirect} = 0;
print "$self: Disabling fast_interrupt_redirect because DCCM not enabled\n";
}
$config{btb}{btb_btag_fold} = 0;
$config{btb}{btb_fold2_index_hash} = 0;
$config{btb}{btb_btag_size} = 31;
if($config{btb}{btb_size}==512){
$config{btb}{btb_index1_hi} = 9;
$config{btb}{btb_index2_hi} = 17;
$config{btb}{btb_index3_hi} = 25;
$config{btb}{btb_array_depth}= 256;
$config{btb}{btb_btag_size} = 5;
} elsif($config{btb}{btb_size}==256){
$config{btb}{btb_index1_hi} = 8;
$config{btb}{btb_index2_hi} = 15;
$config{btb}{btb_index3_hi} = 22;
$config{btb}{btb_array_depth}= 128;
$config{btb}{btb_btag_size} = 6;
} elsif($config{btb}{btb_size}==128){
$config{btb}{btb_index1_hi} = 7;
$config{btb}{btb_index2_hi} = 13;
$config{btb}{btb_index3_hi} = 19;
$config{btb}{btb_array_depth}= 64;
$config{btb}{btb_btag_size} = 7;
} elsif($config{btb}{btb_size}==64){
$config{btb}{btb_index1_hi} = 6;
$config{btb}{btb_index2_hi} = 11;
$config{btb}{btb_index3_hi} = 16;
$config{btb}{btb_array_depth}= 32;
$config{btb}{btb_btag_size} = 8;
} elsif($config{btb}{btb_size}==32){
$config{btb}{btb_index1_hi} = 5;
$config{btb}{btb_index2_hi} = 9;
$config{btb}{btb_index3_hi} = 13;
$config{btb}{btb_array_depth}= 16;
$config{btb}{btb_btag_size} = 9 unless $config{btb}{btb_fullya};
$config{btb}{btb_btag_fold} = 1;
} elsif($config{btb}{btb_size}<32){
#verif issues require these even though they are not needed
$config{btb}{btb_index1_hi} = 5;
$config{btb}{btb_index2_hi} = 8;
$config{btb}{btb_index3_hi} = 11;
$config{btb}{btb_fullya} = 1;
}
$config{btb}{btb_index2_lo} = $config{btb}{btb_index1_hi}+1;
$config{btb}{btb_index3_lo} = $config{btb}{btb_index2_hi}+1;
$config{btb}{btb_addr_hi} = $config{btb}{btb_index1_hi};
if($config{bht}{bht_size}==2048){
$config{bht}{bht_ghr_size}= 10;
$config{bht}{bht_ghr_range}= "9:0";
$config{bht}{bht_array_depth}= 1024;
$config{bht}{bht_addr_hi}= 11;
} elsif($config{bht}{bht_size}==1024){
$config{bht}{bht_ghr_size}= 9;
$config{bht}{bht_ghr_range}= "8:0";
$config{bht}{bht_array_depth}= 512;
$config{bht}{bht_addr_hi}= 10;
} elsif($config{bht}{bht_size}==512){
$config{bht}{bht_ghr_size}= 8;
$config{bht}{bht_ghr_range}= "7:0";
$config{bht}{bht_array_depth}= 256;
$config{bht}{bht_addr_hi}= 9;
} elsif($config{bht}{bht_size}==256){
$config{bht}{bht_ghr_size}= 7;
$config{bht}{bht_ghr_range}= "6:0";
$config{bht}{bht_addr_hi} = 8;
$config{bht}{bht_array_depth}= 128;
} elsif($config{bht}{bht_size}==128){
$config{bht}{bht_ghr_size}= 6;
$config{bht}{bht_ghr_range}= "5:0";
$config{bht}{bht_addr_hi} = 7;
$config{bht}{bht_array_depth}= 64;
} elsif($config{bht}{bht_size}==64){
$config{bht}{bht_ghr_size}= 5;
$config{bht}{bht_ghr_range}= "4:0";
$config{bht}{bht_addr_hi} = 6;
$config{bht}{bht_array_depth}= 32;
} elsif($config{bht}{bht_size}==32){
$config{bht}{bht_ghr_size}= 4;
$config{bht}{bht_ghr_range}= "3:0";
$config{bht}{bht_addr_hi} = 5;
$config{bht}{bht_array_depth}= 16;
}
$config{bht}{bht_ghr_hash_1} = ($config{bht}{bht_ghr_size} > ($config{btb}{btb_index1_hi}-1));
$config{bht}{bht_hash_string} = &ghrhash($config{btb}{btb_index1_hi}, $config{bht}{bht_ghr_size});
# PIC derived
$config{pic}{pic_base_addr} = (hex($config{pic}{pic_region})<<28) +
(hex($config{pic}{pic_offset}));
$config{pic}{pic_base_addr} = sprintf("0x%x", $config{pic}{pic_base_addr});
$config{pic}{pic_int_words} = int($config{pic}{pic_total_int}/32 +0.9);
$config{pic}{pic_bits} = 10 + log2($config{pic}{pic_size});
$config{pic}{pic_total_int_plus1} = $config{pic}{pic_total_int} + 1;
$config{pic}{pic_meipl_count} = $config{pic}{pic_total_int};
$config{pic}{pic_meip_count} = $config{pic}{pic_int_words};
$config{pic}{pic_meie_count} = $config{pic}{pic_total_int};
$config{pic}{pic_meipt_count} = $config{pic}{pic_total_int};
$config{pic}{pic_meigwctrl_count} = $config{pic}{pic_total_int};
$config{pic}{pic_meigwclr_count} = $config{pic}{pic_total_int};
$config{icache}{icache_num_bypass_width} = int(log2($config{icache}{icache_num_bypass})) + 1;
$config{icache}{icache_tag_num_bypass_width} = int(log2($config{icache}{icache_tag_num_bypass})) + 1;
$config{core}{lsu_num_nbload_width} = log2($config{core}{lsu_num_nbload});
$config{bus}{lsu_bus_tag} = log2($config{core}{lsu_num_nbload}) + 1;
$config{bus}{ifu_bus_tag} = log2($config{icache}{icache_ln_sz}/8);
$config{dccm}{dccm_sadr} = (hex($config{dccm}{dccm_region})<<28) +
(hex($config{dccm}{dccm_offset}));
$config{dccm}{dccm_sadr} = sprintf("0x%x", $config{dccm}{dccm_sadr});
$config{dccm}{dccm_eadr} = (hex($config{dccm}{dccm_region})<<28) +
(hex($config{dccm}{dccm_offset})) + size($config{dccm}{dccm_size})-1;
$config{dccm}{dccm_eadr} = sprintf("0x%x", $config{dccm}{dccm_eadr});
$config{dccm}{dccm_reserved} = sprintf("0x%x", ($config{dccm}{dccm_size}>=16)? 5120 : ($config{dccm}{dccm_size}*1024)/4);
$config{dccm}{dccm_bits} = ($config{dccm}{dccm_size}==48 ) ? 16 : 10 + log2($config{dccm}{dccm_size});
$config{dccm}{dccm_bank_bits} = log2($config{dccm}{dccm_num_banks});
$config{dccm}{dccm_data_width} = 32;
$config{dccm}{dccm_fdata_width} = $config{dccm}{dccm_data_width} + log2($config{dccm}{dccm_data_width}) + 2;
$config{dccm}{dccm_byte_width} = $config{dccm}{dccm_data_width}/8;
$config{dccm}{dccm_width_bits} = log2($config{dccm}{dccm_byte_width});
$config{dccm}{dccm_index_bits} = $config{dccm}{dccm_bits} - $config{dccm}{dccm_bank_bits} - $config{dccm}{dccm_width_bits};
$config{dccm}{dccm_ecc_width} = log2($config{dccm}{dccm_data_width}) + 2;
$config{dccm}{lsu_sb_bits} = $config{dccm}{dccm_bits};
$config{dccm}{dccm_rows} = ($config{dccm}{dccm_size}==48 ) ? (2**($config{dccm}{dccm_index_bits}-1) + 2**$config{dccm}{dccm_index_bits})/2 : 2**$config{dccm}{dccm_index_bits};
$config{dccm}{dccm_data_cell} = "ram_$config{dccm}{dccm_rows}x39";
$config{icache}{icache_num_lines} = $config{icache}{icache_size}*1024/$config{icache}{icache_ln_sz};
$config{icache}{icache_num_lines_way} = $config{icache}{icache_num_lines}/$config{icache}{icache_num_ways};
$config{icache}{icache_num_lines_bank} = $config{icache}{icache_num_lines}/($config{icache}{icache_num_ways} * $config{icache}{icache_banks_way});
$config{icache}{icache_data_depth} = $config{icache}{icache_num_lines_bank} * $config{icache}{icache_ln_sz} /$config{icache}{icache_bank_width};
$config{icache}{icache_data_index_lo} = log2($config{icache}{icache_bank_width}) + log2($config{icache}{icache_banks_way});
$config{icache}{icache_index_hi} = $config{icache}{icache_data_index_lo} + log2($config{icache}{icache_data_depth}) -1;
$config{icache}{icache_bank_hi} = $config{icache}{icache_data_index_lo} - 1;
$config{icache}{icache_bank_lo} = log2($config{icache}{icache_bank_width});
$config{icache}{icache_tag_index_lo} = log2($config{icache}{icache_ln_sz});
$config{icache}{icache_tag_lo} = log2($config{icache}{icache_num_lines_way}) + $config{icache}{icache_tag_index_lo};
$config{icache}{icache_tag_depth} = $config{icache}{icache_num_lines}/$config{icache}{icache_num_ways};
$config{icache}{icache_data_width} = 8*$config{icache}{icache_bank_width};
$config{icache}{icache_bank_bits} = 1+$config{icache}{icache_bank_hi}-$config{icache}{icache_bank_lo};
$config{icache}{icache_status_bits} = $config{icache}{icache_num_ways}-1;
$config{icache}{icache_num_beats} = ($config{icache}{icache_ln_sz}==64) ? 8 : 4;
$config{icache}{icache_beat_bits} = ($config{icache}{icache_ln_sz}==64) ? 3 : 2;
$config{icache}{icache_scnd_last} = ($config{icache}{icache_ln_sz}==64) ? 6 : 2;
$config{icache}{icache_beat_addr_hi} = ($config{icache}{icache_ln_sz}==64) ? 5 : 4;
if (($config{icache}{icache_ecc})) {
$config{icache}{icache_fdata_width} = $config{icache}{icache_data_width} + 7;
$config{icache}{icache_data_cell} = "ram_$config{icache}{icache_data_depth}x$config{icache}{icache_fdata_width}";
$config{icache}{icache_tag_cell} = ($config{icache}{icache_tag_depth} == 32) ? "ram_$config{icache}{icache_tag_depth}x26" : "ram_$config{icache}{icache_tag_depth}x25";
}
else {
$config{icache}{icache_fdata_width} = $config{icache}{icache_data_width} + 4;
$config{icache}{icache_data_cell} = "ram_$config{icache}{icache_data_depth}x$config{icache}{icache_fdata_width}";
$config{icache}{icache_tag_cell} = "ram_$config{icache}{icache_tag_depth}x21";
}
$config{pic}{pic_total_int_plus1} = $config{pic}{pic_total_int} + 1;
# Defines with explicit values in the macro name
$config{dccm}{"dccm_num_banks_$config{dccm}{dccm_num_banks}"} = "";
$config{dccm}{"dccm_size_$config{dccm}{dccm_size}"} = "";
# If ICCM offset not explicitly provided, align to TOP of the region
if ($top_align_iccm && ($config{iccm}{iccm_offset} eq $iccm_offset) && ($config{iccm}{iccm_size} < 32)) {
$config{iccm}{iccm_region} = "0xa";
print "$self: Setting default iccm region to region $config{iccm}{iccm_region}\n";
$config{iccm}{iccm_offset} = sprintf("0x%08x",256*1024*1024-size($config{iccm}{iccm_size}));
print "$self: Aligning default iccm offset to top of region @ $config{iccm}{iccm_offset}\n";
}
$config{iccm}{iccm_sadr} = (hex($config{iccm}{iccm_region})<<28) +
(hex($config{iccm}{iccm_offset}));
$config{iccm}{iccm_sadr} = sprintf("0x%08x", $config{iccm}{iccm_sadr});
$config{iccm}{iccm_eadr} = (hex($config{iccm}{iccm_region})<<28) +
(hex($config{iccm}{iccm_offset})) + size($config{iccm}{iccm_size})-1;
$config{iccm}{iccm_eadr} = sprintf("0x%08x", $config{iccm}{iccm_eadr});
$config{iccm}{iccm_reserved} = sprintf("0x%x", ($config{iccm}{iccm_size}>30)? 4096 : ($config{iccm}{iccm_size}*1024)/4);
$config{iccm}{iccm_bits} = 10 + log2($config{iccm}{iccm_size});
$config{iccm}{iccm_bank_bits} = log2($config{iccm}{iccm_num_banks}); //-1;
$config{iccm}{iccm_index_bits} = $config{iccm}{iccm_bits} - $config{iccm}{iccm_bank_bits} - 2; # always 4 bytes
$config{iccm}{iccm_rows} = 2**$config{iccm}{iccm_index_bits};
$config{iccm}{iccm_data_cell} = "ram_$config{iccm}{iccm_rows}x39";
$config{iccm}{iccm_bank_hi} = 2+$config{iccm}{iccm_bank_bits}-1;
$config{iccm}{iccm_bank_index_lo} = 1+$config{iccm}{iccm_bank_hi};
# Defines with explicit values in the macro name
$config{iccm}{"iccm_num_banks_$config{iccm}{iccm_num_banks}"} = "";
$config{iccm}{"iccm_size_$config{iccm}{iccm_size}"} = "";
# Track used regions
$regions_used{hex($config{iccm}{iccm_region})} = 1;
$regions_used{hex($config{dccm}{dccm_region})} = 1;
$regions_used{hex($config{pic}{pic_region})} = 1;
$regions_used{hex($config{reset_vec})>>28} = 1;
# Find an unused region for serial IO
for (my $rgn = 15;$rgn >= 0; $rgn--) {
if (($rgn != hex($config{iccm}{iccm_region})) &&
($rgn != hex($config{dccm}{dccm_region})) &&
($rgn != (hex($config{pic}{pic_region})))) {
$config{memmap}{serialio} = ($rgn << 28) + (22<<18);
$regions_used{$rgn} = 1;
last;
}
}
$config{memmap}{serialio} = sprintf("0x%08x", $config{memmap}{serialio});
# Find an unused region for external data
for (my $rgn = 15;$rgn >= 0; $rgn--) {
if (($rgn != hex($config{iccm}{iccm_region})) &&
($rgn != hex($config{dccm}{dccm_region})) &&
($rgn != (hex($config{memmap}{serialio})>>28)) &&
($rgn != (hex($config{pic}{pic_region})))) {
$config{memmap}{external_data} = ($rgn << 28) + (22<<18);
$regions_used{$rgn} = 1;
last;
}
}
$config{memmap}{external_data} = sprintf("0x%08x", $config{memmap}{external_data});
#
# Unused region for second data
for (my $rgn = 15;$rgn >= 0; $rgn--) {
if (($rgn != hex($config{iccm}{iccm_region})) &&
($rgn != hex($config{dccm}{dccm_region})) &&
($rgn != (hex($config{memmap}{serialio})>>28)) &&
($rgn != (hex($config{memmap}{external_data})>>28)) &&
($rgn != (hex($config{pic}{pic_region})))) {
$config{memmap}{external_data_1} = ($rgn << 28);
$regions_used{$rgn} = 1;
last;
}
}
$config{memmap}{external_data_1} = sprintf("0x%08x", $config{memmap}{external_data_1});
#$config{memmap}{consoleio} = hex($config{memmap}{serialio}) + 0x100;
#$config{memmap}{consoleio} = sprintf("0x%x", $config{memmap}{consoleio});
# Find an unused region for debug_sb_memory data
for (my $rgn = 15;$rgn >= 0; $rgn--) {
if (($rgn != hex($config{iccm}{iccm_region})) &&
($rgn != hex($config{dccm}{dccm_region})) &&
($rgn != (hex($config{memmap}{serialio})>>28)) &&
($rgn != (hex($config{memmap}{external_data})>>28)) &&
($rgn != (hex($config{memmap}{external_data_1})>>28)) &&
($rgn != (hex($config{pic}{pic_region})))) {
$config{memmap}{debug_sb_mem} = ($rgn << 28) + (22<<18);
$regions_used{$rgn} = 1;
last;
}
}
$config{memmap}{debug_sb_mem} = sprintf("0x%08x", $config{memmap}{debug_sb_mem});
# Create the memory map hole for random testing
# Only do this if masks are not enabled already
if (hex($config{protection}{data_access_enable0}) > 0 ||
hex($config{protection}{data_access_enable1}) > 0 ||
hex($config{protection}{data_access_enable2}) > 0 ||
hex($config{protection}{data_access_enable3}) > 0 ||
hex($config{protection}{data_access_enable4}) > 0 ||
hex($config{protection}{data_access_enable5}) > 0 ||
hex($config{protection}{data_access_enable6}) > 0 ||
hex($config{protection}{data_access_enable7}) > 0 ||
hex($config{protection}{inst_access_enable0}) > 0 ||
hex($config{protection}{inst_access_enable1}) > 0 ||
hex($config{protection}{inst_access_enable2}) > 0 ||
hex($config{protection}{inst_access_enable3}) > 0 ||
hex($config{protection}{inst_access_enable4}) > 0 ||
hex($config{protection}{inst_access_enable5}) > 0 ||
hex($config{protection}{inst_access_enable6}) > 0 ||
hex($config{protection}{inst_access_enable7}) > 0 ||
$config{memmap}{external_mem_hole} eq "default disabled"){
delete($config{memmap}{external_mem_hole}) ;
} else {
# Unused region to create a memory map hole, if not already specified
if ($config{memmap}{external_mem_hole} eq 'derived, overridable') {
for (my $rgn = 15;$rgn >= 0; $rgn--) {
if (!defined($regions_used{$rgn})) {
$config{memmap}{external_mem_hole} = ($rgn << 28);
$regions_used{$rgn} = 1;
last;
}
}
} else {
my $rgn = hex($config{memmap}{external_mem_hole})>>28;
$config{memmap}{external_mem_hole} = ($rgn << 28);
$regions_used{$rgn} =1;
}
my $hreg = $config{memmap}{external_mem_hole}>>28;
$config{protection}{data_access_addr0} = sprintf("0x%x", (($hreg^8)&8)<<28);
$config{protection}{data_access_mask0} = "0x7fffffff";
$config{protection}{data_access_addr1} = sprintf("0x%x", ($hreg&8) << 28 |(($hreg^4)&4)<<28);
$config{protection}{data_access_mask1} = "0x3fffffff";
$config{protection}{data_access_addr2} = sprintf("0x%x", ($hreg&12) <<28 | (($hreg^2)&2) <<28);
$config{protection}{data_access_mask2} = "0x1fffffff";
$config{protection}{data_access_addr3} = sprintf("0x%x", ($hreg&14) << 28 |(($hreg^1)&1)<<28);
$config{protection}{data_access_mask3} = "0x0fffffff";
$config{protection}{data_access_enable0} = "1";
$config{protection}{data_access_enable1} = "1";
$config{protection}{data_access_enable2} = "1";
$config{protection}{data_access_enable3} = "1";
$config{protection}{inst_access_addr0} = sprintf("0x%x", (($hreg^8)&8)<<28);
$config{protection}{inst_access_mask0} = "0x7fffffff";
$config{protection}{inst_access_addr1} = sprintf("0x%x", ($hreg&8) << 28 |(($hreg^4)&4)<<28);
$config{protection}{inst_access_mask1} = "0x3fffffff";
$config{protection}{inst_access_addr2} = sprintf("0x%x", ($hreg&12) <<28 | (($hreg^2)&2) <<28);
$config{protection}{inst_access_mask2} = "0x1fffffff";
$config{protection}{inst_access_addr3} = sprintf("0x%x", ($hreg&14) << 28 |(($hreg^1)&1)<<28);
$config{protection}{inst_access_mask3} = "0x0fffffff";
$config{protection}{inst_access_enable0} = "1";
$config{protection}{inst_access_enable1} = "1";
$config{protection}{inst_access_enable2} = "1";
$config{protection}{inst_access_enable3} = "1";
$config{memmap}{external_mem_hole} = sprintf("0x%08x", $config{memmap}{external_mem_hole});
}
#Define 5 unused regions for used in TG
my $unrg = 0;
foreach my $unr (reverse(0 .. 15)) {
if (!defined($regions_used{$unr})) {
$config{memmap}{"unused_region$unrg"} = sprintf("0x%08x",($unr << 28));
$regions_used{$unr} = 1;
$unrg++;
}
}
if ($target eq "baseline") {
$config{reset_vec} = $config{iccm}{iccm_sadr};
$config{testbench}{magellan} = 1;
print "$self: Setting reset_vec = ICCM start address for Baseline\n";
}
# Output bit-width specifiers for these variables
our %widths = (
"dccm_region" => "4",
"dccm_offset" => "28",
"dccm_sadr" => "32",
"dccm_eadr" => "32",
"pic_region" => "4",
"pic_offset" => "10",
"pic_base_addr" => "32",
"iccm_region" => "4",
"iccm_offset" => "10",
"iccm_sadr" => "32",
"iccm_eadr" => "32",
"bus_prty_default" => "2",
"inst_access_enable0" => "1",
"inst_access_enable1" => "1",
"inst_access_enable2" => "1",
"inst_access_enable3" => "1",
"inst_access_enable4" => "1",
"inst_access_enable5" => "1",
"inst_access_enable6" => "1",
"inst_access_enable7" => "1",
"data_access_enable0" => "1",
"data_access_enable1" => "1",
"data_access_enable2" => "1",
"data_access_enable3" => "1",
"data_access_enable4" => "1",
"data_access_enable5" => "1",
"data_access_enable6" => "1",
"data_access_enable7" => "1",
);
#}}}
print "\nSweRV configuration for target=$target\n\n";
dump_define("","", \%config,[]);
#print Dumper(\%config);
#print Dumper(\%width);
#print Dumper(\%sets);
#print Dumper(\%unsets);
# Sanity checks
check_addr_align("dccm", hex($config{dccm}{dccm_sadr}), $config{dccm}{dccm_size}*1024);
check_addr_align("iccm", hex($config{iccm}{iccm_sadr}), $config{iccm}{iccm_size}*1024);
check_addr_align("pic", hex($config{pic}{pic_base_addr}), $config{pic}{pic_size}*1024);
# Prevent overlap of internal memories
if ((hex($config{pic}{pic_region}) == hex($config{iccm}{iccm_region})) && (hex($config{pic}{pic_offset}) == hex($config{iccm}{iccm_offset}))) {
die "$self: ERROR! PIC and ICCM blocks collide (region $config{iccm}{iccm_region}, offset $config{pic}{pic_offset})!\n";
}
if ((hex($config{pic}{pic_region}) == hex($config{dccm}{dccm_region})) && (hex($config{pic}{pic_offset}) == hex($config{dccm}{dccm_offset}))) {
die "$self: ERROR! PIC and DCCM blocks collide (region $config{dccm}{dccm_region}, offset $config{pic}{pic_offset})!\n";
}
if ((hex($config{iccm}{iccm_region}) == hex($config{dccm}{dccm_region})) && (hex($config{iccm}{iccm_offset}) == hex($config{dccm}{dccm_offset}))) {
die "$self: ERROR! ICCM and DCCM blocks collide (region $config{iccm}{iccm_region}, offset $config{dccm}{dccm_offset})!\n";
}
#printf( "axi4 %s\n",$config{"testbench"}{"build_axi4"});
#printf( "ahb_lite %s\n",$config{"testbench"}{"build_ahb_lite"});
#printf( "axi_native %s\n",$config{"testbench"}{"build_axi_native"});
if( $target eq "el2_formal_axi" ) {
$config{testbench}{build_axi_native} = 1;
$config{testbench}{build_axi4} = 1;
print( "\$config{testbench}{build_axi_native} = $config{testbench}{build_axi_native} \n" );
print( "\$config{testbench}{build_axi4 } = $config{testbench}{build_axi4 } \n" );
}
if (($config{testbench}{build_ahb_lite} == 1)) {
delete $config{testbench}{build_axi4};
$config{testbench}{build_axi_native}=1;
$verilog_parms{build_axi4} = 0;
}
elsif (($config{testbench}{build_axi4} == 1)) {
$config{testbench}{build_axi_native}=1;
delete $config{testbench}{build_ahb_lite};
$verilog_parms{build_ahb_lite} = 0;
}
elsif (($config{testbench}{build_axi_native} == 1)) {
die("illegal to set build_axi_native w/out build_axi4");
}
#printf( "axi4 %s\n",$config{"testbench"}{"build_axi4"});
#printf( "ahb_lite %s\n",$config{"testbench"}{"build_ahb_lite"});
#printf( "axi_native %s\n",$config{"testbench"}{"build_axi_native"});
# Over-ride MFDC reset value for AXI.
# Disable Bus barrier and 64b for AXI
if (defined($config{"testbench"}{"build_axi_native"}) && ($config{"testbench"}{"build_axi_native"} ne "0")) {
if (! (defined($config{testbench}{build_ahb_lite}) && $config{testbench}{build_ahb_lite} ne "0")) {
$config{csr}{mfdc}{reset} = "0x00070040" if exists $config{csr}{mfdc};
}
}
# parm processing before any values are deleted from the hash
delete $config{core}{fpga_optimize} if ($config{core}{fpga_optimize} == 0);
print "$self: Writing $tdfile\n";
print "$self: Writing $paramfile\n";
open (FILE1, ">$tdfile") || die "Cannot open $tdfile for writing $!\n";
open (FILE2, ">$paramfile") || die "Cannot open $paramfile for writing $!\n";
print_header("//");
gen_define("","`", \%config, \%verilog_parms, \@verilog_vars);
dump_parms(\%verilog_parms);
close FILE1;
close FILE2;
$config{config_key}="32'hdeadbeef";
# end parms
# deletes
if (($load_to_use_plus1==0) && !grep(/load_to_use_plus1/, @sets)) { delete $config{"core"}{"load_to_use_plus1"}; }
if (($iccm_enable==0) && !grep(/iccm_enable/, @sets)) { delete $config{"iccm"}{"iccm_enable"}; }
# new code to handle the -set=parm=0 value correctly for common_defines.vh
$c=$config{core}{load_to_use_plus1}; if ($c==0 && !grep(/load_to_use_plus1=1/, @sets)) { delete $config{"core"}{"load_to_use_plus1"}; }
$c=$config{core}{opensource}; if ($c==0 && !grep(/opensource=1/, @sets)) { delete $config{"core"}{"opensource"}; }
$c=$config{core}{verilator}; if ($c==0 && !grep(/verilator=1/, @sets)) { delete $config{"core"}{"verilator"}; }
$c=$config{core}{div_new}; if ($c==0 && !grep(/div_new=1/, @sets)) { delete $config{"core"}{"div_new"}; }
# not needed
#$c=$config{core}{div_bit}; if ($c==0 && !grep(/div_bit=1/, @sets)) { delete $config{"core"}{"div_bit"}; }
$c=$config{iccm}{iccm_enable}; if ($c==0 && !grep(/iccm_enable=1/, @sets)) { delete $config{"iccm"}{"iccm_enable"}; }
$c=$config{btb}{btb_enable}; if ($c==0 && !grep(/btb_enable=1/, @sets)) { delete $config{"btb"}{"btb_enable"}; }
$c=$config{dccm}{dccm_enable}; if ($c==0 && !grep(/dccm_enable=1/, @sets)) { delete $config{"dccm"}{"dccm_enable"}; }
$c=$config{icache}{icache_waypack}; if ($c==0 && !grep(/icache_waypack=1/, @sets)) { delete $config{"icache"}{"icache_waypack"}; }
$c=$config{icache}{icache_enable}; if ($c==0 && !grep(/icache_enable=1/, @sets)) { delete $config{"icache"}{"icache_enable"}; }
$c=$config{icache}{icache_2banks}; if ($c==0 && !grep(/icache_2banks=1/, @sets)) { delete $config{"icache"}{"icache_2banks"}; }
$c=$config{pic}{pic_2cycle}; if ($c==0 && !grep(/pic_2cycle=1/, @sets)) { delete $config{"pic"}{"pic_2cycle"}; }
$c=$config{btb}{btb_fullya}; if ($c==0 && !grep(/btb_fullya=1/, @sets)) { delete $config{"btb"}{"btb_fullya"}; }
if ($target eq "default") {
}
elsif (($config{"testbench"}{"build_axi4"} == 1)) {
delete $config{"testbench"}{"build_ahb_lite"};
delete $config{"testbench"}{"build_axi_native_ahb"};
}
elsif (($config{"testbench"}{"build_ahb_lite"} == 1)) {
delete $config{"testbench"}{"build_axi4"};
delete $config{"testbench"}{"build_axi_native"};
delete $config{"testbench"}{"build_axi_native_ahb"};
}
elsif (($config{"testbench"}{"build_axi_native_ahb"} == 1)) {
delete $config{"testbench"}{"build_axi4"};
delete $config{"testbench"}{"build_axi_native_ahb"};
}
elsif (($config{"testbench"}{"build_axi_native"} == 1)) {
die("illegal to set build_axi_native w/out build_axi4");
}
else {
delete $config{"testbench"}{"build_ahb_lite"};
delete $config{"testbench"}{"build_axi4"};
delete $config{"testbench"}{"build_axi_native"};
delete $config{"testbench"}{"build_axi_native_ahb"};
}
##################### Add dumper routines here ##########################
#
# Dump Verilog $RV_ROOT/configs/common_defines.vh
print "$self: Writing $vlogfile\n";
open (FILE, ">$vlogfile") || die "Cannot open $vlogfile for writing $!\n";
print_header("//");
print FILE "`define RV_ROOT \"".$ENV{RV_ROOT}."\"\n";
gen_define("","`", \%config, "", \@verilog_vars);
close FILE;
print "$self: Writing $asmfile\n";
open (FILE, ">$asmfile") || die "Cannot open $asmfile for writing $!\n";
# Dump ASM/C $RV_ROOT/diags/env/defines.h
print_header("//");
gen_define("","#", \%config, "", \@asm_vars, \@asm_overridable);
close FILE;
# add `define PHYSICAL 1
# remove `undef RV_ICCM_ENABLE
my $pddata='
`include "common_defines.vh"
`undef RV_ASSERT_ON
`undef TEC_RV_ICG
`define RV_PHYSICAL 1
';
print "$self: Writing $pdfile\n";
open (FILE, ">$pdfile") || die "Cannot open $pdfile for writing $!\n";
# Dump PD $RV_ROOT/$RV_ROOT/configs/pd_defines.vh
print_header("//");
printf (FILE "$pddata");
close FILE;
print "$self: Writing $whisperfile\n";
dump_whisper_config(\%config, $whisperfile);
# PIC address map based on config
`$ENV{RV_ROOT}/tools/picmap -t $config{pic}{pic_total_int} > $build_path/pic_map_auto.h`;
# Perl vars for use by scripts
print "$self: Writing $perlfile\n";
open (FILE, ">$perlfile") || die "Cannot open $perlfile for writing $!\n";
print_header("# ");
print FILE "# To use this in a perf script, use 'require \$RV_ROOT/configs/config.pl'\n";
print FILE "# Reference the hash via \$config{name}..\n\n\n";
print FILE Data::Dumper->Dump([\%config], [ qw(*config) ]);
print FILE "1;\n";
close FILE;
# Default linker script
gen_default_linker_script();
# Done ##################################################################
#
exit(0);
# ###################### Helper subroutines ##########################{{{
# Convert size in kilobytes to real value
sub size {#{{{
my $ksize = shift;
my $size = sprintf("%d",$ksize*1024);
return $size;
}#}}}
# Print the defines with prefix
sub print_define {#{{{
my ($sym, $key,$value, $override) = @_;
my $lprefix = $prefix if ($key !~ /$no_prefix/);
if ($sym eq "`") {
if (defined($widths{$key})) {
$value =~ s/^(0x)*/$widths{$key}'h/;
} else {
$value =~ s/^0x/'h/;
}
}
if ($defines_case eq "U") {
print FILE "${sym}ifndef \U$lprefix$key\E\n" if ($override);
print FILE "${sym}define \U$lprefix$key\E $value\n";
print FILE "${sym}endif\n" if ($override);
} else {
print FILE "${sym}ifndef $lprefix$key\n" if ($override);
print FILE "${sym}define $lprefix$key $value\n";
print FILE "${sym}endif\n" if ($override);
}
}#}}}
# print header
sub print_header {#{{{
my $cs = shift;
print FILE "$cs NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE\n";
print FILE "$cs This is an automatically generated file by $ENV{USER} on ",`date`;
print FILE "$cs\n$cs cmd: $self @argv_orig \n";
print FILE "$cs\n";
}#}}}
# evaluate derivations
sub derive {#{{{
my $eqn = shift;
return sprintf("0x%x", eval($eqn));
}#}}}
# traverse the database and extract the key/value pair
sub gen_define {#{{{
my $matched = shift;
my $prefix = shift;
my $hash = @_[0];
my $parms = @_[1];
my @printvars = @{@_[2]};
my @overridable = @{@_[3]} if defined @_[3];
my $re = join("|",@printvars);
$re = qr/($re)/;
#print Dumper($hash);
foreach my $key (keys %$hash) {
next if $key eq "csr";
#print "looking at $key:$matched ($re)\n";
if (defined($unsets{$key})) {
print "$self:unsetting $key\n";
delete($config{$key});
if ($parms and defined($parms->{$key})) {
$parms->{$key} = 0;
}
next
}
if (defined($sets{$key}) && $sets{$key} ne $$hash{$key}) {
if (($$hash{$key} =~ /derived/i) && ($$hash{$key} !~ /overridable/i)) {
die ("$self: ERROR! $key is a derived and non-overridable parameter!\n");
} else {
print "$self: Overriding $key value $$hash{$key} with $sets{$key}\n";
$$hash{$key} = $sets{$key};
}
}
my $value = $$hash{$key};
if (ref($value) eq "HASH") {
if ($key =~ /$re/) {
$matched = 1;
}
gen_define($matched,$prefix, $value, $parms, \@printvars, \@overridable);
$matched = 0;
} elsif (ref($value) eq "ARRAY") {
# print "$key : @{$value}\n";
$matched = 0;
} else {
if ($matched eq "1" || $key =~ /$re/) {
if($value =~ /derive\(.*\)/o) {
$value = eval($value);
}
my $override = grep(/^$key$/, @overridable);
print_define($prefix, $key, $value, $override) if ($value !~ /derived/);
#printf("$key = $value\n");
if ($parms and defined($parms->{$key})) {
$value=decimal($value);
#printf("verilog parm $key = $value %s\n",$parms->{$key});
$value=d2b($key,$value,$parms->{$key});
#printf("verilog parm $key = $value\n");
$parms->{$key}=$value;
}
}
}
}
}#}}}
sub dump_define {#{{{
my $matched = shift;
my $prefix = shift;
my $hash = @_[0];
my @printvars = @{@_[1]};
my @overridable = @{@_[2]} if defined @_[2];
my $re = join("|",@printvars);
$re = qr/($re)/;
#print Dumper($hash);
foreach my $key (keys %$hash) {
next if $key eq "csr";
next unless $matched || grep(/^$key$/,@dvars);
#print "looking at $key:$matched ($re)\n";
if (defined($unsets{$key})) {
print "$self:unsetting $key\n";
delete($config{$key});
next
}
if (defined($sets{$key}) && $sets{$key} ne $$hash{$key}) {
if (($$hash{$key} =~ /derived/i) && ($$hash{$key} !~ /overridable/i)) {
die ("$self: ERROR! $key is a derived and non-overridable parameter!\n");
} else {
print "$self: Overriding $key value $$hash{$key} with $sets{$key}\n";
$$hash{$key} = $sets{$key};
}
}
my $value = $$hash{$key};
if (ref($value) eq "HASH") {
if ($key =~ /$re/) {
$matched = 1;
}
dump_define($matched,$prefix, $value, \@printvars, \@overridable);
$matched = 0;
} elsif (ref($value) eq "ARRAY") {
# print "$key : @{$value}\n";
$matched = 0;
} else {
if ($matched eq "1" || $key =~ /$re/) {
if($value =~ /derive\(.*\)/o) {
$value = eval($value);
}
printf ("swerv: %-30s = $value\n",$key) if ($value !~ /derived/);
}
}
}
}#}}}
# Perform cmd line set/unset ############################################{{{
sub map_set_unset {
if (scalar(@sets)) {
print "$self: Set(s) requested : @sets\n";
foreach (@sets) {
my ($key,$value) = m/(\w+)=*(\w+)*/o;
$value = 1 if (!defined($value));
$sets{$key} = $value;
}
}
if (scalar(@unsets)) {
print "$self: Unset(s) requested : @unsets\n";
foreach (@unsets) {
$unsets{$_} = 1;
}
}
} #}}}
#}}}
# If arg looks like a hexadecimal string, then convert it to decimal.#{{{
# Otherwise, return arg.
sub decimal {
my ($x) = @_;
return hex($x) if $x =~ /^0x/o;
return $x;
}#}}}
# Collect memory protection specs (array of address pairs) in the given
# resutls array. Tag is either "data" or "inst".
sub collect_mem_protection {#{{{
my ($tag, $config, $results) = @_;
return unless exists $config{protection};
my $prot = $config{protection};
my $enable_tag = $tag . "_access_enable";
my $addr_tag = $tag . "_access_addr";
my $mask_tag = $tag . "_access_mask";
foreach my $key (keys %{$prot}) {
next unless $key =~ /^$enable_tag(\d+)$/;
my $ix = $1;
my $enable = $prot->{$key};
if ($enable !~ /[01]$/) {
warn("Invalid value for protection entry $key: $enable\n");
next;
}
next unless ($enable eq "1" or $enable eq "1'b1");
if (! exists $prot->{"$addr_tag$ix"}) {
warn("Missing $addr_tag$ix\n");
next;
}
if (! exists $prot->{"$mask_tag$ix"}) {
warn("Missing $mask_tag$ix\n");
next;
}
my $addr = $prot->{"$addr_tag$ix"};
my $mask = $prot->{"$mask_tag$ix"};
if ($addr !~ /^0x[0-9a-fA-F]+$/) {
warn("Invalid $addr_tag$ix: $addr\n");
next;
}
if ($mask !~ /^0x[0-9a-fA-F]+$/) {
warn("Invalid $mask_tag$ix: $mask\n");
next;
}
if ((hex($addr) & hex($mask)) != 0) {
warn("Protection mask bits overlap address bits in $tag mask $mask and addr $addr\n");
}
if ($mask !~ /^0x0*[137]?f*$/) {
warn("Protection $tag mask ($mask) must have all its one bits to the right of its zero bits\n");
next;
}
my $start = hex($addr) & ~hex($mask) & 0xffffffff;
my $end = (hex($addr) | hex($mask)) & 0xffffffff;
$start = sprintf("0x%08x", $start);
$end = sprintf("0x%08x", $end);
push(@{$results}, [ $start, $end ]);
}
}#}}}
# Collect the memory mapped registers associated with the pic (platform
# interrup controller) to include in the whisper.json file.
sub collect_mem_mapped_regs {#{{{
my ($pic, $results) = @_;
my $default_mask = 0;
$results->{default_mask} = $default_mask;
my $addr = hex($pic->{pic_region})*256*1024*1024 + hex($pic->{pic_offset});
$results->{address} = sprintf("0x%x", $addr);
$results->{size} = sprintf("0x%x", $pic->{pic_size}*1024);
my @names = qw ( mpiccfg meipl meip meie meigwctrl meigwclr meidels );
$results->{registers} = {};
foreach my $name (@names) {
my $tag = "pic_${name}_offset";
next unless exists $pic->{$tag};
my %item;
my $offset = hex($pic->{$tag});
$offset += 4 if ($name ne 'mpiccfg' and $name ne 'meip');
$item{address} = sprintf("0x%x", $addr + $offset);
$item{mask} = $pic->{"pic_${name}_mask"};
$item{count} = $pic->{"pic_${name}_count"};
$results->{registers}{$name} = \%item;
}
}#}}}
sub dump_whisper_config{#{{{
my ($config, $path) = @_;
open(my $fh, ">", "$path") or die ("Failed to open $path for writing: $!\n");
# Put the configuration parameters relevant to whisper into a hash
# in preparation for a JSON dump.
my %jh; # Json hash
# Collect top-level integer entries.
foreach my $tag (qw( harts xlen )) {
$jh{$tag} = $config{$tag} + 0 if exists $config{$tag};
}
# Collect top-level string/hex entries.
foreach my $tag (qw ( reset_vec nmi_vec num_mmode_perf_regs max_mmode_perf_event
even_odd_trigger_chains)) {
$jh{$tag} = $config{$tag} if exists $config{$tag};
}
# Collect memory map configs.
my (@inst_mem_prot, @data_mem_prot);
collect_mem_protection("inst", $config, \@inst_mem_prot);
collect_mem_protection("data", $config, \@data_mem_prot);
$jh{memmap}{inst} = [@inst_mem_prot] if @inst_mem_prot;
$jh{memmap}{data} = [@data_mem_prot] if @data_mem_prot;
$config{memmap}{consoleio} = $config{memmap}{serialio} if exists $config{memmap}{serialio};
foreach my $tag (qw ( size page_size serialio consoleio)) {
$jh{memmap}{$tag} = $config{memmap}{$tag} if exists $config{memmap}{$tag};
}
# Collect load/store-error rollback parameter.
if (exists $config{testbench} and exists $config{testbench}{sterr_rollback}) {
$jh{store_error_rollback} = $config{testbench}{sterr_rollback};
}
if (exists $config{testbench} and exists $config{testbench}{lderr_rollback}) {
$jh{load_error_rollback} = $config{testbench}{lderr_rollback};
}
# Collect dccm configs
if (exists $config{dccm} and $config{dccm}{dccm_enable}) {
$jh{dccm}{region} = $config{dccm}{dccm_region};
$jh{dccm}{size} = 1024*decimal($config{dccm}{dccm_size}); # From 1k to bytes
$jh{dccm}{offset} = $config{dccm}{dccm_offset};
$jh{dccm}{size} = sprintf("0x%x", $jh{dccm}{size});
}
# Collect icccm configs.
if (exists $config{iccm} and $config{iccm}{iccm_enable}) {
$jh{iccm}{region} = $config{iccm}{iccm_region};
$jh{iccm}{size} = 1024*decimal($config{iccm}{iccm_size}); # From 1k to bytes
$jh{iccm}{offset} = $config{iccm}{iccm_offset};
$jh{iccm}{size} = sprintf("0x%x", $jh{iccm}{size});
}
# Collect CSRs
$jh{csr} = $config{csr} if exists $config{csr};
# Collect CSRs not included in verilog.
my @removed_csrs;
if (! $config{core}{timer_legal_en}) {
push(@removed_csrs, $_) for qw (mitcnt0 mitbnd0 mitctl0
mitcnt1 mitbnd1 mitctl1);
}
# Collect fast interrupt enable.
if (exists $config{core}{fast_interrupt_redirect}) {
$jh{fast_interrupt_redirect} = $config{core}{fast_interrupt_redirect};
# meicpct CSR is not built if fast interrupt.
push(@removed_csrs, 'meicpct') if $jh{fast_interrupt_redirect};
}
# Remove CSRs not configured into verilog.
delete $jh{csr}{$_} foreach @removed_csrs;
# Collect zb extension configs
$jh{enable_zbb} = $config{core}{bitmanip_zbb};
$jh{enable_zbs} = $config{core}{bitmanip_zbs};
$jh{enable_zba} = $config{core}{bitmanip_zba};
$jh{enable_zbc} = $config{core}{bitmanip_zbc};
$jh{enable_zbe} = $config{core}{bitmanip_zbe};
$jh{enable_zbf} = $config{core}{bitmanip_zbf};
$jh{enable_zbp} = $config{core}{bitmanip_zbp};
$jh{enable_zbr} = $config{core}{bitmanip_zbr};
# Collect pic configs.
if (exists $config{pic}) {
my %mem_mapped;
collect_mem_mapped_regs($config{pic}, \%mem_mapped);
$jh{'memory_mapped_registers'} = \%mem_mapped;
}
# Collect performance events. Uncomment when RTL ready.
if (exists $config{perf_events}) {
$jh{mmode_perf_events} = $config{perf_events};
}
# Make atomic instructions illegal outside of DCCM.
$jh{amo_illegal_outside_dccm} = "true";
# Make ld/st instructions trigger misaligned exceptions if base
# address (value in rs1) and effective address refer to regions of
# different types.
$jh{effective_address_compatible_with_base} = "true";
# Collect triggers.
$jh{triggers} = $config{triggers} if exists $config{triggers};
# Dump JSON config file.
my $json = JSON->new->allow_nonref;
my $text = $json->pretty->encode(\%jh);
print($fh $text);
close $fh;
}#}}}
# Checker for iccm/dccm/pic sub-region address alignment. Address must be a multiple
# of size or next higher power of 2 if size is not a power of 2.
sub check_addr_align {#{{{
my ($section, $addr, $size) = @_;
die("Invalid $section size: $size\n") if $size <= 0;
my $log_size = log2($size);
my $p2 = 1 << $log_size;
$size = 2*$p2 if $size != $p2;
if (($addr % $size) != 0) {
printf("Address of $section area(0x%x) is not a multiple of its size (0x%x)\n",
$addr, $size);
exit(1);
}
}#}}}
sub log2 {#{{{
my ($n) = @_;
return log($n)/log(2);
}#}}}
sub b2d {#{{{
my ($v) = @_;
$v = oct("0b" . $v);
return($v);
}#}}}
sub d2b {#{{{
my ($key,$v,$LEN) = @_;
my $repeat;
$v = sprintf "%b",$v;
if (length($v)<$LEN) {
$repeat=$LEN-length($v);
$v="0"x$repeat.$v;
}
elsif (length($v)>$LEN) {
die("d2b: parm $key value $v > len $LEN");
}
return($v);
}#}}}
sub invalid_mask {#{{{
my ($m) = @_;
if ($m =~ /^0x(0)*([137]?f+)$/) { return(0); }
return(1);
}#}}}
sub b2h {#{{{
my ($bin) = @_;
# Make input bit string a multiple of 4
$bin = substr("0000",length($bin)%4) . $bin if length($bin)%4;
my ($hex, $nybble) = ("");
while (length($bin)) {
($nybble,$bin) = (substr($bin,0,4), substr($bin,4));
$nybble = eval "0b$nybble";
$hex .= substr("0123456789ABCDEF", $nybble, 1);
}
return $hex;
}#}}}
# BHT index is a hash of the GHR and PC_HASH
sub ghrhash{#{{{
my($btb_index_hi,$ghr_size) = @_;
$btb_size = $btb_index_hi - 1;
my $ghr_hi = $ghr_size - 1;
my $ghr_lo = $btb_size;
my $ghr_start = "{";
if($ghr_size > $btb_size){
return "{ghr[$ghr_hi:$ghr_lo], hashin[$btb_index_hi:2]^ghr[$ghr_lo-1:0]} // cf1";
}
else {
return "{hashin[$ghr_size+1:2]^ghr[$ghr_size-1:0]}// cf2";
}
}#}}}
sub dump_parms {#{{{
my ($hash) = @_;
my ($bvalue, $blen, $upper);
printf(FILE1 "typedef struct packed {\n");
foreach my $key (sort keys %$hash) {
$bvalue=$hash->{$key};
$blen=length($bvalue);
$upper=$key;
$upper=~ tr/a-z/A-Z/;
if ($blen==1) {
printf(FILE1 "\tbit %-10s $upper;\n");
}
else {
printf(FILE1 "\tbit %-10s $upper;\n",sprintf("[%d:0]",$blen-1));
}
}
printf(FILE1 "} el2_param_t;\n\n");
my $bcat="";
my $parmcnt=0;
foreach my $key (sort keys %$hash) {
#printf("// $key = %s\n",$verilog_parms{$key});
$bcat.=$hash->{$key};
$parmcnt++;
}
my $bvalue="";
my $pcnt=0;
my $delim=",";
my $msb;
printf(FILE2 "parameter el2_param_t pt = '{\n");
foreach my $key (sort keys %$hash) {
$upper=$key;
$upper=~ tr/a-z/A-Z/;
$pcnt++;
if ($pcnt==$parmcnt) { undef $delim; }
if ($hash->{$key} eq "0") { $hash->{$key}="0000"; }
$msb=substr($hash->{$key},0,4); # require upper 4b to be 0
if ($msb ne "0000") { die("parameter $upper upper 4b must be 0"); }
printf(FILE2 "\t%-22s : %d\'h%-10s $delim\n",$upper,length($hash->{$key}),b2h($hash->{$key}));
}
printf(FILE2 "}\n");
printf(FILE2 "// parameter el2_param_t pt = %d'h%s\n",length($bcat),b2h($bcat));
}#}}}
sub gen_default_linker_script {#{{{
open (FILE, ">$linkerfile") || die "Cannot open $linkerfile for writing $!\n";
print "$self: Writing $linkerfile\n";
print FILE "/*\n";
print_header();
my $io = "0xd0580000";
$io = $config{memmap}{serialio} if exists $config{memmap}{serialio};
my $iccm = ""; my $iccm_ctl = "";
if (exists $config{iccm} and $config{iccm}{iccm_enable} and $text_in_iccm) {
my $sa = $config{iccm}{iccm_sadr}; my $ea = $config{iccm}{iccm_eadr};
$iccm = " . = $sa ;";
$iccm_ctl = " . = 0xfffffff0; .iccm.ctl . : { LONG($sa); LONG($ea) }" ;
}
my $sa = $config{memmap}{external_data}; my $dccm_ctl = "";
if (exists $config{dccm} and $config{dccm}{dccm_enable}) {
$sa = $config{dccm}{dccm_sadr};
$dccm_ctl = " . = 0xfffffff8; .data.ctl : { LONG($sa); LONG(STACK) }" ;
}
my $data_loc = " . = $sa ;";
print FILE "*/\n";
print FILE <<"EOF";
OUTPUT_ARCH( "riscv" )
ENTRY(_start)
SECTIONS
{
. = $config{reset_vec};
.text.init . : { *(.text.init) }
$iccm
.text . : { *(.text) }
_end = .;
. = $io;
.data.io . : { *(.data.io) }
$data_loc
.data : ALIGN(0x800) { *(.*data) *(.rodata*)}
.bss : {BSS_START = .; *(.*bss)}
BSS_END = .;
STACK = ALIGN(16) + 0x1000;
$iccm_ctl
$dccm_ctl
}
EOF
close FILE;
} #}}}