OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [mor1kx-5.0/] [rtl/] [verilog/] [mor1kx_pcu.v] - Rev 48

Compare with Previous | Blame | View Log

/* ****************************************************************************
  This Source Code Form is subject to the terms of the
  Open Hardware Description License, v. 1.0. If a copy
  of the OHDL was not distributed with this file, You
  can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
 
  Description: mor1kx Perfomance Counters Unit
 
  Copyright (C) 2016 Authors
 
  Author(s): Alexey Baturo <baturo.alexey@gmail.com>
 
***************************************************************************** */
 
`include "mor1kx-defines.v"
 
module mor1kx_pcu
  #(
    parameter OPTION_PERFCOUNTERS_NUM = 7
  )
  (
   input clk,
   input rst,
 
   // SPR Bus interface
   input         spr_access_i,
   input         spr_we_i,
   input         spr_re_i,
   input [15:0]  spr_addr_i,
   input [31:0]  spr_dat_i,
   output        spr_bus_ack,
   output [31:0] spr_dat_o,
 
   // Current cpu mode: user/supervisor
   input         spr_sys_mode_i,
   // Events that can occur
   input         pcu_event_load_i,            // track load insn
   input         pcu_event_store_i,           // track store insn
   input         pcu_event_ifetch_i,          // track insn fetch
   input         pcu_event_dcache_miss_i,     // track data cache miss
   input         pcu_event_icache_miss_i,     // track insn cache miss
   input         pcu_event_ifetch_stall_i,    // track SOME stall
   input         pcu_event_lsu_stall_i,       // track LSU stall
   input         pcu_event_brn_stall_i,       // track brn miss
   input         pcu_event_dtlb_miss_i,       // track data tlb miss
   input         pcu_event_itlb_miss_i,       // track insn tlb miss
   input         pcu_event_datadep_stall_i    // track SOME stall
   );
 
   // Registers
   reg [31:0]    pcu_pccr[0:OPTION_PERFCOUNTERS_NUM];
   reg [31:0]    pcu_pcmr[0:OPTION_PERFCOUNTERS_NUM];
 
   wire pcu_pccr_access;
   wire pcu_pcmr_access;
 
   // check if we access pcu
   // TODO: generate this signals according to present units
   assign pcu_pccr_access =
     spr_access_i &
     ((`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR0_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR1_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR2_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR3_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR4_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR5_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR6_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCCR7_ADDR)));
 
   assign pcu_pcmr_access =
     spr_access_i &
     ((`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR0_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR1_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR2_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR3_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR4_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR5_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR6_ADDR)) |
      (`SPR_OFFSET(spr_addr_i) == `SPR_OFFSET(`OR1K_SPR_PCMR7_ADDR)));
 
   // put data on data bus
   assign spr_bus_ack = spr_access_i;
   assign spr_dat_o   = (spr_access_i & pcu_pccr_access & spr_re_i) ? pcu_pccr[spr_addr_i[2:0]] :
                        (spr_access_i & pcu_pcmr_access & spr_re_i & spr_sys_mode_i) ? pcu_pcmr[spr_addr_i[2:0]] :
                        0;
   genvar pcu_num;
   generate
      for(pcu_num = 0; pcu_num < OPTION_PERFCOUNTERS_NUM + 1; pcu_num = pcu_num + 1) begin: pcu_generate
         wire [`OR1K_PCMR_DDS:`OR1K_PCMR_LA] pcu_events_active;
         wire [`OR1K_PCMR_DDS:`OR1K_PCMR_LA] pcu_events_hit;
 
         assign pcu_events_active =
            (pcu_event_load_i << `OR1K_PCMR_LA) |
            (pcu_event_store_i << `OR1K_PCMR_SA) |
            (pcu_event_ifetch_i << `OR1K_PCMR_IF) |
            (pcu_event_dcache_miss_i << `OR1K_PCMR_DCM) |
            (pcu_event_icache_miss_i << `OR1K_PCMR_ICM) |
            (pcu_event_ifetch_stall_i << `OR1K_PCMR_IFS) |
            (pcu_event_lsu_stall_i << `OR1K_PCMR_LSUS) |
            (pcu_event_brn_stall_i << `OR1K_PCMR_BS) |
            (pcu_event_dtlb_miss_i << `OR1K_PCMR_DTLBM) |
            (pcu_event_itlb_miss_i << `OR1K_PCMR_ITLBM) |
            (pcu_event_datadep_stall_i << `OR1K_PCMR_DDS);
 
         assign pcu_events_hit =
            pcu_events_active & pcu_pcmr[pcu_num];
 
         always @(posedge clk `OR_ASYNC_RST) begin
            if (rst) begin
               pcu_pccr[pcu_num] <= 32'd0;
               pcu_pcmr[pcu_num] <= 32'd0 | 1 << `OR1K_PCMR_CP;
            // we could write pcu registers only in system mode
            end else if (spr_we_i && spr_sys_mode_i) begin
               if (pcu_pccr_access & (spr_addr_i[2:0] == pcu_num))
                  pcu_pccr[pcu_num] <= spr_dat_i;
               // WPE are not implemented, hence we do not update WPE part
               if (pcu_pcmr_access && (spr_addr_i[2:0] == pcu_num)) begin
                  pcu_pcmr[pcu_num][`OR1K_PCMR_DDS:`OR1K_PCMR_CISM] <=
                     spr_dat_i[`OR1K_PCMR_DDS:`OR1K_PCMR_CISM];
               end
            end else if (((pcu_pcmr[pcu_num][`OR1K_PCMR_CISM] & spr_sys_mode_i) |
                       (pcu_pcmr[pcu_num][`OR1K_PCMR_CIUM] & ~spr_sys_mode_i))) begin
               pcu_pccr[pcu_num] <= pcu_pccr[pcu_num] +
                  pcu_events_hit[`OR1K_PCMR_LA] +
                  pcu_events_hit[`OR1K_PCMR_SA] +
                  pcu_events_hit[`OR1K_PCMR_IF] +
                  pcu_events_hit[`OR1K_PCMR_DCM] +
                  pcu_events_hit[`OR1K_PCMR_ICM] +
                  pcu_events_hit[`OR1K_PCMR_IFS] +
                  pcu_events_hit[`OR1K_PCMR_LSUS] +
                  pcu_events_hit[`OR1K_PCMR_BS] +
                  pcu_events_hit[`OR1K_PCMR_DTLBM] +
                  pcu_events_hit[`OR1K_PCMR_ITLBM] +
                  pcu_events_hit[`OR1K_PCMR_DDS];
            end
         end
      end
   endgenerate
 
endmodule // mor1kx_pcu
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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