⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 make_interrupt_vector.pl

📁 altera NIOS软核系统 中断矢量使用例子
💻 PL
字号:
#Copyright (C)2004 Altera Corporation#Any megafunction design, and related net list (encrypted or decrypted),#support information, device programming or simulation file, and any other#associated documentation or information provided by Altera or a partner#under Altera's Megafunction Partnership Program may be used only to#program PLD devices (but not masked PLD devices) from Altera.  Any other#use of such megafunction design, net list, support information, device#programming or simulation file, or any other related documentation or#information is prohibited for any other purpose, including, but not#limited to modification, reverse engineering, de-compiling, or use with#any other silicon devices, unless such use is explicitly licensed under#a separate agreement with Altera or a megafunction partner.  Title to#the intellectual property, including patents, copyrights, trademarks,#trade secrets, or maskworks, embodied in any such megafunction design,#net list, support information, device programming or simulation file, or#any other related documentation or information provided by Altera or a#megafunction partner, remains with Altera, the megafunction partner, or#their respective licensors.  No other licenses, including any licenses#needed under any third party's intellectual property, are provided herein.#Copying or modifying any file, or portion thereof, to which this notice#is attached violates this copyright.# make_interrupt_vector.pl# # This Europa module implements a Nios II custom instruction# that generates an interrupt vector to reduce interrupt latency.# It priority encodes the pending interrupts (lowest number interrupt# is the highest priority) and multiplies the IRQ number by 8# to create an offset.  If there are no interrupts pending,# the offset is set to a negative value.## The custom instruction examines the value of the CPU ipending and# estatus registers.use europa_all;use e_custom_instruction_slave;use strict;$| = 1;     # Always flush stderr##################### Global constants #####################our $datapath_sz = 32;# Number of bytes allocated for each entry in the interrupt vector table.our $bytes_per_vector = 8;# Pointers to functions that generate instructions.our %ci_slave_gen_funcs = (        "interrupt_vector" => \&make_interrupt_vector,    );#main{    my @arguments = (@ARGV);    my $project = e_project->new(@arguments);    # Make a copy so we don't write-back derived parameter values, etc.    my %Opt = copy_of_hash($project->WSA());    validate_options(\%Opt);    my $module = $project->top();    my $marker = e_default_module_marker->new($module);    # Create each instruction/slave specified by PTF file.    my $slave_hash = $project->spaceless_module_ptf()->{SLAVE};    foreach my $slave_name (keys(%$slave_hash)) {        my $slave_SBI = $slave_hash->{$slave_name}{SYSTEM_BUILDER_INFO};        # Skip disabled slaves.        if ($slave_SBI->{Is_Enabled} eq "0") {            next;        }        # Skip slaves that aren't custom instruction slaves.        if ($slave_hash->{$slave_name}{SYSTEM_BUILDER_INFO}{Bus_Type}           ne "nios_custom_instruction") {            next;        }        my $func = $ci_slave_gen_funcs{$slave_name};        if (!defined($func)) {            my @supported_funcs = keys(%ci_slave_gen_funcs);            print("Cannot generate slave $slave_name. Supported: @supported_funcs\n");            ribbit("Bye now");        }        # Call generator function for slave.        my $submodule = &$func(\%Opt, $project, $module, $slave_SBI);        e_instance->add({module => $submodule});    }    $project->output();     # DONE!}sub make_interrupt_vector{    my ($Opt, $project, $parent, $slave_SBI) = @_;    # Get id of associated custom instruction master port on CPU.     my $cpu_master_ref = $slave_SBI->{MASTERED_BY};    my @cpu_master_ids = (keys %$cpu_master_ref);    my $cpu_master_id = $cpu_master_ids[0];    # Split id into module name and interface name fields.    my ($cpu_name, $cpu_interface) = split(/\//, $cpu_master_id);    my $submodule =       e_module->new({name => $cpu_name . "_interrupt_vector_compute_result"});    my $marker = e_default_module_marker->new($submodule);    e_port->adds(      ["result"                  => $datapath_sz,      "out" ],      ["ipending"                => 32,                "in"  ],      ["estatus"                 => 1,                 "in"  ],    );    e_custom_instruction_slave->new({        name     => "interrupt_vector",        type_map => {            result             => "result",            ipending           => "ipending",            estatus            => "estatus",            },    })->within($parent);    my $offset_expr = compute_result($project, $cpu_name);    e_assign->adds(      # Interrupts are only taken if estatus.pie is 1 and ipending is non-zero.      [["result_no_interrupts", 1],          "(ipending == 0) | (estatus == 0)"],              [["result_offset", $datapath_sz-1], $offset_expr],      [["result", $datapath_sz], "{result_no_interrupts, result_offset}"],    );    return $submodule;}# Determine which interrupts are connected to my associated CPU.subcompute_result{    my ($project, $cpu_name) = @_;    my $data_master_id = join("/", $cpu_name, "data_master");    my $data_master_irq_hash_ref = $project->get_module_slave_hash(      ["SYSTEM_BUILDER_INFO", "IRQ_MASTER", $data_master_id,       "IRQ_Number"]);    # Create a list of interrupts connected to the CPU.    my @irqs;    my $irq;    foreach $irq (values(%$data_master_irq_hash_ref)) {        # Make sure irq is a decimal number.        next unless ($irq =~ /^\d+$/);        # Make sure irq is unique.        my $is_dup_irq = 0;        foreach my $dup_irq (@irqs) {            if ($irq == $dup_irq) {                $is_dup_irq = 1;            }        }        next if ($is_dup_irq);        push(@irqs, $irq);    }    # Sort irqs in numerically ascending order.    @irqs = sort {$a <=> $b} @irqs;    # Create the expression to compute the offset.    # The lowest numbered irq has the highest priority.    my $offset_expr;    my $num_irqs = scalar(@irqs);    if ($num_irqs > 0) {        for (my $index = 0; $index < $num_irqs; $index++) {            my $irq = $irqs[$index];            my $offset = $irq * $bytes_per_vector;            if ($index == ($num_irqs - 1)) {                # Last interrupt so use default.                $offset_expr .= "$offset";            } else {                $offset_expr .= "ipending[$irq] ? $offset : ";            }        }    } else {        # No interrupts so set offset expression to zero.        $offset_expr = "0";    }    return $offset_expr;}sub validate_options{    my ($Opt) = @_;    validate_parameter({hash    => $Opt,                        name    => "Data_Width",                        type    => "integer",                        default => $datapath_sz,                        allowed => [$datapath_sz],                       });}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -