You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

537 lines
16 KiB
Verilog

// © IBM Corp. 2020
// Licensed under the Apache License, Version 2.0 (the "License"), as modified by
// the terms below; you may not use the files in this repository except in
// compliance with the License as modified.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
//
// Modified Terms:
//
// 1) For the purpose of the patent license granted to you in Section 3 of the
// License, the "Work" hereby includes implementations of the work of authorship
// in physical form.
//
// 2) Notwithstanding any terms to the contrary in the License, any licenses
// necessary for implementation of the Work that are available from OpenPOWER
// via the Power ISA End User License Agreement (EULA) are explicitly excluded
// hereunder, and may be obtained from OpenPOWER under the terms and conditions
// of the EULA.
//
// Unless required by applicable law or agreed to in writing, the reference design
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
// for the specific language governing permissions and limitations under the License.
//
// Additional rights, including the ability to physically implement a softcore that
// is compliant with the required sections of the Power ISA Specification, are
// available at no cost under the terms of the OpenPOWER Power ISA EULA, which can be
// obtained (along with the Power ISA) here: https://openpowerfoundation.org.
`timescale 1 ns / 1 ns
// *********************************************************************
//
// This is the ENTITY for rv_perv
//
// *********************************************************************
module rv_perv( // 0 = ibm umbra, 1 = xilinx, 2 = ibm mpg
`include "tri_a2o.vh"
inout vdd,
inout gnd,
input clk,
input rst,
input rp_rv_ccflush_dc,
input rp_rv_func_sl_thold_3,
input rp_rv_gptr_sl_thold_3,
input rp_rv_sg_3,
input rp_rv_fce_3,
input an_ac_scan_diag_dc,
input an_ac_scan_dis_dc_b,
input d_mode,
output func_sl_thold_1,
output fce_1,
output sg_1,
output clkoff_dc_b,
output act_dis,
output [0:9] delay_lclkr_dc,
output [0:9] mpw1_dc_b,
output mpw2_dc_b,
input gptr_scan_in,
output gptr_scan_out,
input scan_in,
output scan_out,
//------------------------------------------------------------------------------------------------------------
// Debug and Perf
//------------------------------------------------------------------------------------------------------------
input [0:8*`THREADS-1] fx0_rvs_perf_bus,
input [0:31] fx0_rvs_dbg_bus,
input [0:8*`THREADS-1] fx1_rvs_perf_bus,
input [0:31] fx1_rvs_dbg_bus,
input [0:8*`THREADS-1] lq_rvs_perf_bus,
input [0:31] lq_rvs_dbg_bus,
input [0:8*`THREADS-1] axu0_rvs_perf_bus,
input [0:31] axu0_rvs_dbg_bus,
input [0:`THREADS-1] spr_msr_gs,
input [0:`THREADS-1] spr_msr_pr,
input pc_rv_trace_bus_enable,
input [0:10] pc_rv_debug_mux_ctrls,
input pc_rv_event_bus_enable,
input [0:2] pc_rv_event_count_mode,
input [0:39] pc_rv_event_mux_ctrls,
input [0:4*`THREADS-1] rv_event_bus_in,
output [0:4*`THREADS-1] rv_event_bus_out,
output [0:31] debug_bus_out,
input [0:31] debug_bus_in,
input [0:3] coretrace_ctrls_in,
output [0:3] coretrace_ctrls_out
);
wire func_sl_thold_2;
wire gptr_sl_thold_2;
wire sg_2;
wire fce_2;
wire gptr_sl_thold_1;
wire func_sl_thold_1_int;
wire sg_1_int;
wire gptr_sl_thold_0;
wire func_sl_thold_0;
wire force_t;
wire sg_0;
wire gptr_sio;
wire [0:9] prv_delay_lclkr_dc;
wire [0:9] prv_mpw1_dc_b;
wire prv_mpw2_dc_b;
wire prv_act_dis;
wire prv_clkoff_dc_b;
// Debug and Perf
wire trc_act;
wire evt_act;
wire delay_lclkr;
wire mpw1_b;
wire mpw2_b;
wire [0:31] debug_bus_mux;
wire [0:3] coretrace_ctrls_mux;
wire [0:10] debug_mux_ctrls;
wire [0:39] event_mux_ctrls;
wire [0:2] event_count_mode;
wire [0:`THREADS-1] spr_msr_gs_q;
wire [0:`THREADS-1] spr_msr_pr_q;
wire [0:`THREADS-1] event_en;
wire [0:32*`THREADS-1] event_bus_in;
wire [0:4*`THREADS-1] event_bus_d;
wire [0:4*`THREADS-1] event_bus_q;
wire [0:31] dbg_group0;
wire [0:31] dbg_group1;
wire [0:31] dbg_group2;
wire [0:31] dbg_group3;
// Unused Signals
(* analysis_not_referenced="TRUE" *)
wire act0_dis_dc;
(* analysis_not_referenced="TRUE" *)
wire d0_mode_dc;
(* analysis_not_referenced="TRUE" *)
wire clkoff1_dc_b;
(* analysis_not_referenced="TRUE" *)
wire act1_dis_dc;
(* analysis_not_referenced="TRUE" *)
wire d1_mode_dc;
(* analysis_not_referenced="TRUE" *)
wire nc_mpw2_dc_b;
(* analysis_not_referenced="TRUE" *)
wire unused;
wire func_sl_thold_0_b = 0; // wtf: dangling test sig
//------------------------------------------------------------------------------------------------------------
// Scan Chains
//------------------------------------------------------------------------------------------------------------
parameter debug_bus_offset = 0 + 0;
parameter debug_mux_offset = debug_bus_offset + 32;
parameter event_bus_offset = debug_mux_offset + 11;
parameter event_count_offset = event_bus_offset + 4*`THREADS;
parameter spr_msr_gs_offset = event_count_offset + 3;
parameter spr_msr_pr_offset = spr_msr_gs_offset + `THREADS;
parameter event_mux_ctrls_offset = spr_msr_pr_offset + `THREADS;
parameter coretrace_ctrls_offset = event_mux_ctrls_offset + 40;
parameter scan_right = coretrace_ctrls_offset + 4;
wire [0:scan_right-1] siv;
wire [0:scan_right-1] sov;
assign unused = an_ac_scan_dis_dc_b ;
tri_plat #(.WIDTH(4))
perv_3to2_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.flush(rp_rv_ccflush_dc),
.din({rp_rv_func_sl_thold_3, rp_rv_gptr_sl_thold_3, rp_rv_sg_3, rp_rv_fce_3}),
.q({func_sl_thold_2, gptr_sl_thold_2, sg_2, fce_2})
);
tri_plat #(.WIDTH(4))
perv_2to1_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.flush(rp_rv_ccflush_dc),
.din({func_sl_thold_2, gptr_sl_thold_2, sg_2, fce_2}),
.q({func_sl_thold_1_int, gptr_sl_thold_1, sg_1_int, fce_1})
);
assign func_sl_thold_1 = func_sl_thold_1_int;
assign sg_1 = sg_1_int;
tri_plat #(.WIDTH(3))
perv_1to0_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.flush(rp_rv_ccflush_dc),
.din({gptr_sl_thold_1 , func_sl_thold_1_int, sg_1_int}),
.q({gptr_sl_thold_0, func_sl_thold_0, sg_0})
);
tri_lcbor
perv_lcbor(
.clkoff_b(prv_clkoff_dc_b),
.thold(func_sl_thold_0),
.sg(sg_0),
.act_dis(prv_act_dis),
.force_t(force_t),
.thold_b(func_sl_thold_0_b)
);
// Pipeline mapping of mpw1_b and delay_lclkr
// RF0
// RF1 0
// EX1 1
// EX2 2
// EX3 3
// EX4 4
// EX5 5
// EX6 6
// EX7 7
tri_lcbcntl_mac
perv_lcbctrl0(
.vdd(vdd),
.gnd(gnd),
.sg(sg_0),
.clk(clk),
.rst(rst),
.scan_in(gptr_scan_in),
.scan_diag_dc(an_ac_scan_diag_dc),
.thold(gptr_sl_thold_0),
.clkoff_dc_b(prv_clkoff_dc_b),
.delay_lclkr_dc(prv_delay_lclkr_dc[0:4]),
.act_dis_dc(act0_dis_dc),
.d_mode_dc(d0_mode_dc),
.mpw1_dc_b(prv_mpw1_dc_b[0:4]),
.mpw2_dc_b(prv_mpw2_dc_b),
.scan_out(gptr_sio)
);
tri_lcbcntl_mac
perv_lcbctrl1(
.vdd(vdd),
.gnd(gnd),
.sg(sg_0),
.clk(clk),
.rst(rst),
.scan_in(gptr_sio),
.scan_diag_dc(an_ac_scan_diag_dc),
.thold(gptr_sl_thold_0),
.clkoff_dc_b(clkoff1_dc_b),
.delay_lclkr_dc(prv_delay_lclkr_dc[5:9]),
.act_dis_dc(act1_dis_dc),
.d_mode_dc(d1_mode_dc),
.mpw1_dc_b(prv_mpw1_dc_b[5:9]),
.mpw2_dc_b(nc_mpw2_dc_b),
.scan_out(gptr_scan_out)
);
//Outputs
assign delay_lclkr_dc[0:9] = prv_delay_lclkr_dc[0:9];
assign mpw1_dc_b[0:9] = prv_mpw1_dc_b[0:9];
assign mpw2_dc_b = prv_mpw2_dc_b;
//never disable act pins, they are used functionally
assign prv_act_dis = 1'b0;
assign act_dis = prv_act_dis;
assign clkoff_dc_b = prv_clkoff_dc_b;
//------------------------------------------------------------------------------------------------------------
// Perf bus
//------------------------------------------------------------------------------------------------------------
assign event_en = ( spr_msr_pr_q & {`THREADS{event_count_mode[0]}}) | //-- User
((~spr_msr_pr_q) & spr_msr_gs_q & {`THREADS{event_count_mode[1]}}) | //-- Guest Supervisor
((~spr_msr_pr_q) & (~spr_msr_gs_q) & {`THREADS{event_count_mode[2]}}); //-- Hypervisor
assign event_bus_in[ 0: 7] = fx0_rvs_perf_bus[0:7] & {8{event_en[0]}};
assign event_bus_in[ 8:15] = fx1_rvs_perf_bus[0:7] & {8{event_en[0]}};
assign event_bus_in[16:23] = lq_rvs_perf_bus[0:7] & {8{event_en[0]}};
assign event_bus_in[24:31] = axu0_rvs_perf_bus[0:7] & {8{event_en[0]}};
tri_event_mux1t #(.EVENTS_IN(32), .EVENTS_OUT(4))
event_mux0(
.vd(vdd),
.gd(gnd),
.event_bus_in(rv_event_bus_in[0:3]),
.event_bus_out(event_bus_d[0:3]),
.unit_events_in(event_bus_in[1:31]),
.select_bits(event_mux_ctrls[0:19])
);
`ifndef THREADS1
assign event_bus_in[32:39] = fx0_rvs_perf_bus[8:15] & {8{event_en[1]}};
assign event_bus_in[40:47] = fx1_rvs_perf_bus[8:15] & {8{event_en[1]}};
assign event_bus_in[48:55] = lq_rvs_perf_bus[8:15] & {8{event_en[1]}};
assign event_bus_in[56:63] = axu0_rvs_perf_bus[8:15] & {8{event_en[1]}};
tri_event_mux1t #(.EVENTS_IN(32), .EVENTS_OUT(4))
event_mux1(
.vd(vdd),
.gd(gnd),
.event_bus_in(rv_event_bus_in[4:7]),
.event_bus_out(event_bus_d[4:7]),
.unit_events_in(event_bus_in[32:63]),
.select_bits(event_mux_ctrls[20:39])
);
`endif
assign rv_event_bus_out = event_bus_q;
//------------------------------------------------------------------------------------------------------------
// Debug bus
//------------------------------------------------------------------------------------------------------------
assign dbg_group0 = fx0_rvs_dbg_bus[0:31] ;
assign dbg_group1 = fx1_rvs_dbg_bus[0:31] ;
assign dbg_group2 = lq_rvs_dbg_bus[0:31] ;
assign dbg_group3 = axu0_rvs_dbg_bus[0:31] ;
tri_debug_mux4 #(.DBG_WIDTH(32))
dbg_mux(
.select_bits(debug_mux_ctrls),
.trace_data_in(debug_bus_in),
.dbg_group0(dbg_group0),
.dbg_group1(dbg_group1),
.dbg_group2(dbg_group2),
.dbg_group3(dbg_group3),
.trace_data_out(debug_bus_mux),
.coretrace_ctrls_in(coretrace_ctrls_in),
.coretrace_ctrls_out(coretrace_ctrls_mux)
);
//------------------------------------------------------------------------------------------------------------
// Latches
//------------------------------------------------------------------------------------------------------------
assign trc_act = pc_rv_trace_bus_enable;
assign evt_act = pc_rv_event_bus_enable;
assign delay_lclkr = prv_delay_lclkr_dc[0];
assign mpw1_b = prv_mpw1_dc_b[0];
assign mpw2_b = prv_mpw2_dc_b;
tri_rlmreg_p #(.WIDTH(32), .INIT(0))
debug_bus_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(trc_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[debug_bus_offset:debug_bus_offset + 32 - 1]),
.scout(sov[debug_bus_offset:debug_bus_offset + 32 - 1]),
.din(debug_bus_mux),
.dout(debug_bus_out)
);
tri_rlmreg_p #(.WIDTH(11), .INIT(0))
debug_mux_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(trc_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[debug_mux_offset:debug_mux_offset + 11 - 1]),
.scout(sov[debug_mux_offset:debug_mux_offset + 11 - 1]),
.din(pc_rv_debug_mux_ctrls),
.dout(debug_mux_ctrls)
);
tri_rlmreg_p #(.WIDTH(4*`THREADS), .INIT(0))
event_bus_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(evt_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[event_bus_offset:event_bus_offset + 4*`THREADS - 1]),
.scout(sov[event_bus_offset:event_bus_offset + 4*`THREADS - 1]),
.din(event_bus_d),
.dout(event_bus_q)
);
tri_rlmreg_p #(.WIDTH(3), .INIT(0))
event_count_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(evt_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[event_count_offset:event_count_offset + 3 - 1]),
.scout(sov[event_count_offset:event_count_offset + 3 - 1]),
.din(pc_rv_event_count_mode),
.dout(event_count_mode)
);
tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0))
spr_msr_gs_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(evt_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[spr_msr_gs_offset:spr_msr_gs_offset + `THREADS - 1]),
.scout(sov[spr_msr_gs_offset:spr_msr_gs_offset + `THREADS - 1]),
.din(spr_msr_gs),
.dout(spr_msr_gs_q)
);
tri_rlmreg_p #(.WIDTH(`THREADS), .INIT(0))
spr_msr_pr_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(evt_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[spr_msr_pr_offset:spr_msr_pr_offset + `THREADS - 1]),
.scout(sov[spr_msr_pr_offset:spr_msr_pr_offset + `THREADS - 1]),
.din(spr_msr_pr),
.dout(spr_msr_pr_q)
);
tri_rlmreg_p #(.WIDTH(40), .INIT(0))
event_mux_ctrls_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(evt_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[event_mux_ctrls_offset:event_mux_ctrls_offset + 40 - 1]),
.scout(sov[event_mux_ctrls_offset:event_mux_ctrls_offset + 40 - 1]),
.din(pc_rv_event_mux_ctrls),
.dout(event_mux_ctrls)
);
tri_rlmreg_p #(.WIDTH(4), .INIT(0))
core_trace_ctrls_reg(
.vd(vdd),
.gd(gnd),
.clk(clk),
.rst(rst),
.act(trc_act),
.thold_b(func_sl_thold_0_b),
.sg(sg_0),
.force_t(force_t),
.delay_lclkr(delay_lclkr),
.mpw1_b(mpw1_b),
.mpw2_b(mpw2_b),
.d_mode(d_mode),
.scin(siv[coretrace_ctrls_offset:coretrace_ctrls_offset + 4 - 1]),
.scout(sov[coretrace_ctrls_offset:coretrace_ctrls_offset + 4 - 1]),
.din(coretrace_ctrls_mux),
.dout(coretrace_ctrls_out)
);
//------------------------------------------------------------------------------------------------------------
// Scan Connections
//------------------------------------------------------------------------------------------------------------
assign siv[0:scan_right-1] = {sov[1:scan_right-1], scan_in};
assign scan_out = sov[0];
endmodule