Skip to content

Commit

Permalink
Hw: Add Power-Aware Logic to be UPF-Drivable (#40)
Browse files Browse the repository at this point in the history
- Add ports for PMU cluster control signals.
 - Add rst signals for each external cluster, driven by the PMU controller.
 - Add AXI isolation at the cluster interface and control ports for isolation.
  • Loading branch information
Lore0599 authored Sep 26, 2024
1 parent 522d73e commit 460e295
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 140 deletions.
141 changes: 132 additions & 9 deletions hw/chimera_clu_domain.sv
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module chimera_clu_domain
) (
input logic soc_clk_i,
input logic [ ExtClusters-1:0] clu_clk_i,
input logic rst_ni,
input logic [ ExtClusters-1:0] rst_sync_ni,
input logic [ ExtClusters-1:0] widemem_bypass_i,
//-----------------------------
// Interrupt ports
Expand All @@ -45,11 +45,133 @@ module chimera_clu_domain
// Wide AXI ports
//-----------------------------
output wide_out_req_t [ iomsb(Cfg.AxiExtNumWideMst):0] wide_out_req_o,
input wide_out_resp_t [ iomsb(Cfg.AxiExtNumWideMst):0] wide_out_resp_i
input wide_out_resp_t [ iomsb(Cfg.AxiExtNumWideMst):0] wide_out_resp_i,
//-----------------------------
// Isolation control ports
//-----------------------------
input logic [ ExtClusters-1:0] isolate_i,
output logic [ ExtClusters-1:0] isolate_o
);

// Axi parameters
localparam int unsigned AxiWideDataWidth = Cfg.AxiDataWidth * Cfg.MemIslNarrowToWideFactor;
localparam int unsigned AxiWideSlvIdWidth = Cfg.MemIslAxiMstIdWidth + $clog2(Cfg.MemIslWidePorts);
localparam int unsigned AxiSlvIdWidth = Cfg.AxiMstIdWidth + $clog2(
cheshire_pkg::gen_axi_in(Cfg).num_in
);

// Isolated AXI signals
narrow_in_req_t [ iomsb(Cfg.AxiExtNumSlv):0] narrow_in_isolated_req;
narrow_in_resp_t [ iomsb(Cfg.AxiExtNumSlv):0] narrow_in_isolated_resp;
narrow_out_req_t [ iomsb(Cfg.AxiExtNumMst):0] narrow_out_isolated_req;
narrow_out_resp_t [ iomsb(Cfg.AxiExtNumMst):0] narrow_out_isolated_resp;
wide_out_req_t [iomsb(Cfg.AxiExtNumWideMst):0] wide_out_isolated_req;
wide_out_resp_t [iomsb(Cfg.AxiExtNumWideMst):0] wide_out_isolated_resp;

logic [ iomsb(Cfg.AxiExtNumSlv):0] isolated_narrow_in;
logic [ iomsb(Cfg.AxiExtNumMst):0] isolated_narrow_out;
logic [iomsb(Cfg.AxiExtNumWideMst):0] isolated_wide_out;



for (genvar extClusterIdx = 0; extClusterIdx < ExtClusters; extClusterIdx++) begin : gen_clusters

if (IsolateClusters == 1) begin : gen_cluster_iso
// Add AXI isolation at the Narrow Input Interface
axi_isolate #(
.NumPending (Cfg.AxiMaxSlvTrans),
.TerminateTransaction(0),
.AtopSupport (1),
.AxiAddrWidth (Cfg.AddrWidth),
.AxiDataWidth (Cfg.AxiDataWidth),
.AxiIdWidth (AxiSlvIdWidth),
.AxiUserWidth (Cfg.AxiUserWidth),
.axi_req_t (narrow_in_req_t),
.axi_resp_t (narrow_in_resp_t)
) i_iso_narrow_in_cluster (
.clk_i (soc_clk_i),
.rst_ni (rst_sync_ni[extClusterIdx]),
.slv_req_i (narrow_in_req_i[extClusterIdx]),
.slv_resp_o(narrow_in_resp_o[extClusterIdx]),
.mst_req_o (narrow_in_isolated_req[extClusterIdx]),
.mst_resp_i(narrow_in_isolated_resp[extClusterIdx]),
.isolate_i (isolate_i[extClusterIdx]),
.isolated_o(isolated_narrow_in[extClusterIdx])
);

// Add AXI isolation at the Narrow Output Interface.
// Two ports for each cluster: one to convert stray wides, one for the original narrow
for (
genvar narrowOutIdx = 2 * extClusterIdx;
narrowOutIdx < 2 * extClusterIdx + 2;
narrowOutIdx++
) begin : gen_iso_narrow_out
axi_isolate #(
.NumPending (Cfg.AxiMaxSlvTrans),
.TerminateTransaction(0),
.AtopSupport (1),
.AxiAddrWidth (Cfg.AddrWidth),
.AxiDataWidth (Cfg.AxiDataWidth),
.AxiIdWidth (Cfg.AxiMstIdWidth),
.AxiUserWidth (Cfg.AxiUserWidth),
.axi_req_t (narrow_out_req_t),
.axi_resp_t (narrow_out_resp_t)
) i_iso_narrow_out_cluster (
.clk_i (soc_clk_i),
.rst_ni (rst_sync_ni[extClusterIdx]),
.slv_req_i (narrow_out_isolated_req[narrowOutIdx]),
.slv_resp_o(narrow_out_isolated_resp[narrowOutIdx]),
.mst_req_o (narrow_out_req_o[narrowOutIdx]),
.mst_resp_i(narrow_out_resp_i[narrowOutIdx]),
.isolate_i (isolate_i[extClusterIdx]),
.isolated_o(isolated_narrow_out[narrowOutIdx])
);
end : gen_iso_narrow_out

// Add AXI isolation at the Wide Interface
axi_isolate #(
.NumPending (Cfg.AxiMaxSlvTrans),
.TerminateTransaction(0),
.AtopSupport (1),
.AxiAddrWidth (Cfg.AddrWidth),
.AxiDataWidth (AxiWideDataWidth),
.AxiIdWidth (Cfg.MemIslAxiMstIdWidth), // To Check
.AxiUserWidth (Cfg.AxiUserWidth),
.axi_req_t (wide_out_req_t),
.axi_resp_t (wide_out_resp_t)
) i_iso_wide_cluster (
.clk_i (soc_clk_i),
.rst_ni (rst_sync_ni[extClusterIdx]),
.slv_req_i (wide_out_isolated_req[extClusterIdx]),
.slv_resp_o(wide_out_isolated_resp[extClusterIdx]),
.mst_req_o (wide_out_req_o[extClusterIdx]),
.mst_resp_i(wide_out_resp_i[extClusterIdx]),
.isolate_i (isolate_i[extClusterIdx]),
.isolated_o(isolated_wide_out[extClusterIdx])
);

assign isolate_o[extClusterIdx] = isolated_narrow_in[extClusterIdx] &
isolated_narrow_out[2*extClusterIdx+:2] &
isolated_wide_out[extClusterIdx];

end else begin : gen_no_cluster_iso // bypass isolate if not required

assign narrow_in_isolated_req[extClusterIdx] = narrow_in_req_i[extClusterIdx];
assign narrow_in_resp_o[extClusterIdx] = narrow_in_isolated_resp[extClusterIdx];

assign narrow_out_req_o[2*extClusterIdx] = narrow_out_isolated_req[2*extClusterIdx];
assign narrow_out_isolated_resp[2*extClusterIdx] = narrow_out_resp_i[2*extClusterIdx];

assign narrow_out_req_o[2*extClusterIdx+1] = narrow_out_isolated_req[2*extClusterIdx+1];
assign narrow_out_isolated_resp[2*extClusterIdx+1] = narrow_out_resp_i[2*extClusterIdx+1];

assign wide_out_req_o[extClusterIdx] = wide_out_isolated_req[extClusterIdx];
assign wide_out_isolated_resp[extClusterIdx] = wide_out_resp_i[extClusterIdx];

assign isolate_o[extClusterIdx] = '0;

end : gen_no_cluster_iso

chimera_cluster #(
.Cfg (Cfg),
.NrCores (`NRCORES(extClusterIdx)),
Expand All @@ -62,7 +184,7 @@ module chimera_clu_domain
) i_chimera_cluster (
.soc_clk_i (soc_clk_i),
.clu_clk_i (clu_clk_i[extClusterIdx]),
.rst_ni,
.rst_ni (rst_sync_ni[extClusterIdx]),
.widemem_bypass_i (widemem_bypass_i[extClusterIdx]),
.debug_req_i (debug_req_i[`PREVNRCORES(extClusterIdx)+:`NRCORES(extClusterIdx)]),
.meip_i (xeip_i[`PREVNRCORES(extClusterIdx)+:`NRCORES(extClusterIdx)]),
Expand All @@ -72,12 +194,13 @@ module chimera_clu_domain
.cluster_base_addr_i(Cfg.AxiExtRegionStart[extClusterIdx][Cfg.AddrWidth-1:0]),
.boot_addr_i (SnitchBootROMRegionStart[31:0]),

.narrow_in_req_i (narrow_in_req_i[extClusterIdx]),
.narrow_in_resp_flat_o(narrow_in_resp_o[extClusterIdx]),
.narrow_out_req_flat_o(narrow_out_req_o[2*extClusterIdx+:2]),
.narrow_out_resp_i (narrow_out_resp_i[2*extClusterIdx+:2]),
.wide_out_req_flat_o (wide_out_req_o[extClusterIdx]),
.wide_out_resp_i (wide_out_resp_i[extClusterIdx])
.narrow_in_req_i (narrow_in_isolated_req[extClusterIdx]),
.narrow_in_resp_o (narrow_in_isolated_resp[extClusterIdx]),
.narrow_out_req_o (narrow_out_isolated_req[2*extClusterIdx+:2]),
.narrow_out_resp_i(narrow_out_isolated_resp[2*extClusterIdx+:2]),

.wide_out_req_o (wide_out_isolated_req[extClusterIdx]),
.wide_out_resp_i(wide_out_isolated_resp[extClusterIdx])
);

end : gen_clusters
Expand Down
82 changes: 28 additions & 54 deletions hw/chimera_cluster.sv
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: SHL-0.51
//
// Moritz Scherer <scheremo@iis.ee.ethz.ch>
// Lorenzo Leone <lleone@iis.ee.ethz.ch>

module chimera_cluster
import chimera_pkg::*;
Expand All @@ -16,76 +17,49 @@ module chimera_cluster
parameter type narrow_out_req_t = logic,
parameter type narrow_out_resp_t = logic,
parameter type wide_out_req_t = logic,
parameter type wide_out_resp_t = logic,

// !! DO NOT OVERWRITE THESE PARAMETERS
// These parameters are used to provide a flattened interface for the AXI ports (see comments below).
parameter type narrow_in_resp_flat_t = logic [$bits(narrow_in_resp_t)-1:0],
parameter type narrow_out_req_flat_t = logic [$bits(narrow_out_req_t)-1:0],
parameter type wide_out_req_flat_t = logic [ $bits(wide_out_req_t)-1:0]
parameter type wide_out_resp_t = logic
) (

input logic soc_clk_i,
input logic clu_clk_i,
input logic rst_ni,
input logic widemem_bypass_i,
input logic soc_clk_i,
input logic clu_clk_i,
input logic rst_ni,
input logic widemem_bypass_i,
//-----------------------------
// Interrupt ports
//-----------------------------
input logic [ NrCores-1:0] debug_req_i,
input logic [ NrCores-1:0] meip_i,
input logic [ NrCores-1:0] mtip_i,
input logic [ NrCores-1:0] msip_i,
input logic [ NrCores-1:0] debug_req_i,
input logic [ NrCores-1:0] meip_i,
input logic [ NrCores-1:0] mtip_i,
input logic [ NrCores-1:0] msip_i,
//-----------------------------
// Cluster base addressing
//-----------------------------
input logic [ 9:0] hart_base_id_i,
input logic [Cfg.AddrWidth-1:0] cluster_base_addr_i,
input logic [ 31:0] boot_addr_i,
input logic [ 9:0] hart_base_id_i,
input logic [Cfg.AddrWidth-1:0] cluster_base_addr_i,
input logic [ 31:0] boot_addr_i,
//-----------------------------
// Narrow AXI ports
//-----------------------------
input narrow_in_req_t narrow_in_req_i,
output narrow_in_resp_flat_t narrow_in_resp_flat_o,
output narrow_out_req_flat_t [ 1:0] narrow_out_req_flat_o,
input narrow_out_resp_t [ 1:0] narrow_out_resp_i,
input narrow_in_req_t narrow_in_req_i,
output narrow_in_resp_t narrow_in_resp_o,
output narrow_out_req_t [ 1:0] narrow_out_req_o,
input narrow_out_resp_t [ 1:0] narrow_out_resp_i,
//-----------------------------
//Wide AXI ports
//-----------------------------
output wide_out_req_flat_t wide_out_req_flat_o,
input wide_out_resp_t wide_out_resp_i
output wide_out_req_t wide_out_req_o,
input wide_out_resp_t wide_out_resp_i
);

`include "axi/typedef.svh"

/* ------------------------------------------------------------------------------- */
/* Flattened interface signals for UPF structure workaround */
/* ------------------------------------------------------------------------------- */
//
// The UPF standard supported by QuestaSim cannot apply isolation strategies to
// ports with "complex" types, such as AXI ports, which are structures.
// To address this issue, at the interface of each power domain, signals are flattened
// (e.g., narrow_in_resp_flat_o) and then internally reassigned to new structured signals
// (e.g., narrow_in_resp_s), which can be propagated to downstream modules.
//
narrow_out_req_t [1:0] narrow_out_req_s;
narrow_in_resp_t narrow_in_resp_s;
wide_out_req_t wide_out_req_s;

assign narrow_out_req_flat_o = narrow_out_req_s;
assign narrow_in_resp_flat_o = narrow_in_resp_s;
assign wide_out_req_flat_o = wide_out_req_s;

/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */

localparam int WideDataWidth = $bits(wide_out_req_s.w.data);

localparam int WideMasterIdWidth = $bits(wide_out_req_s.aw.id);
localparam int WideDataWidth = $bits(wide_out_req_o.w.data);

localparam int WideMasterIdWidth = $bits(wide_out_req_o.aw.id);
localparam int WideSlaveIdWidth = WideMasterIdWidth + $clog2(Cfg.AxiExtNumWideMst) - 1;

localparam int NarrowSlaveIdWidth = $bits(narrow_in_req_i.aw.id);
localparam int NarrowMasterIdWidth = $bits(narrow_out_req_s[0].aw.id);
localparam int NarrowMasterIdWidth = $bits(narrow_out_req_o[0].aw.id);

typedef logic [Cfg.AddrWidth-1:0] axi_addr_t;
typedef logic [Cfg.AxiUserWidth-1:0] axi_user_t;
Expand Down Expand Up @@ -167,8 +141,8 @@ module chimera_cluster

// SoC side narrow.
.narrow_in_req_i (narrow_in_req_i),
.narrow_in_resp_o (narrow_in_resp_s),
.narrow_out_req_o (narrow_out_req_s),
.narrow_in_resp_o (narrow_in_resp_o),
.narrow_out_req_o (narrow_out_req_o),
.narrow_out_resp_i(narrow_out_resp_i),

// Cluster side narrow
Expand All @@ -182,8 +156,8 @@ module chimera_cluster
end else begin : gen_skip_narrow_adapter // if (ClusterDataWidth != Cfg.AxiDataWidth)

assign clu_axi_narrow_slv_req = narrow_in_req_i;
assign narrow_in_resp_s = clu_axi_narrow_slv_rsp;
assign narrow_out_req_s = clu_axi_narrow_mst_req;
assign narrow_in_resp_o = clu_axi_narrow_slv_rsp;
assign narrow_out_req_o = clu_axi_narrow_mst_req;
assign clu_axi_narrow_mst_rsp = narrow_out_resp_i;

end
Expand Down Expand Up @@ -223,7 +197,7 @@ module chimera_cluster
.clu_narrow_out_req_i (clu_axi_adapter_mst_req),
.clu_narrow_out_resp_o(clu_axi_adapter_mst_resp),

.wide_out_req_o (wide_out_req_s),
.wide_out_req_o (wide_out_req_o),
.wide_out_resp_i (wide_out_resp_i),
.clu_wide_out_req_i (clu_axi_wide_mst_req),
.clu_wide_out_resp_o(clu_axi_wide_mst_resp),
Expand Down
3 changes: 3 additions & 0 deletions hw/chimera_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ package chimera_pkg;

localparam aw_bt ClusterNarrowAxiMstIdWidth = 1;

// Isolate Clusters from SoC
localparam int unsigned IsolateClusters = 0;

function automatic cheshire_cfg_t gen_chimera_cfg();
localparam int AddrWidth = DefaultCfg.AddrWidth;

Expand Down
Loading

0 comments on commit 460e295

Please sign in to comment.