From 797f2dc8bedc5c31bbe191b50d86caae0c6bf6f8 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 25 Apr 2024 15:18:29 +0200 Subject: [PATCH 1/3] Add control register file --- .github/workflows/lint.yml | 3 + Bender.yml | 6 + Makefile | 11 +- src/ctrl_unit/cluster_icache_ctrl.hjson | 138 ++ src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv | 272 +++ src/ctrl_unit/cluster_icache_ctrl_reg_top.sv | 2116 ++++++++++++++++++ src/ctrl_unit/cluster_icache_ctrl_unit.sv | 96 + 7 files changed, 2641 insertions(+), 1 deletion(-) create mode 100644 src/ctrl_unit/cluster_icache_ctrl.hjson create mode 100644 src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv create mode 100644 src/ctrl_unit/cluster_icache_ctrl_reg_top.sv create mode 100644 src/ctrl_unit/cluster_icache_ctrl_unit.sv diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2b6f1c2..bb2a297 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,6 +23,9 @@ jobs: paths: | ./src ./test + exclude_paths: | + ./src/ctrl_unit/cluster_icache_ctrl_reg_top.sv + ./src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv github_token: ${{ secrets.GITHUB_TOKEN }} fail_on_error: true reviewdog_reporter: github-check diff --git a/Bender.yml b/Bender.yml index a5876d1..75db517 100644 --- a/Bender.yml +++ b/Bender.yml @@ -16,6 +16,7 @@ dependencies: tech_cells_generic: { git: "https://github.com/pulp-platform/tech_cells_generic.git", version: 0.2.11 } axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.39.1 } scm: { git: "https://github.com/pulp-platform/scm.git", version: 1.1.0 } + register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.4 } sources: # Source files grouped in levels. Files in level 0 have no dependencies on files in this @@ -37,6 +38,11 @@ sources: # Level 3 - src/snitch_icache.sv - src/snitch_read_only_cache.sv + # Level 4 + - files: # ctrl_unit + - src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv + - src/ctrl_unit/cluster_icache_ctrl_reg_top.sv + - src/ctrl_unit/cluster_icache_ctrl_unit.sv - target: test files: - test/snitch_icache_l0_tb.sv diff --git a/Makefile b/Makefile index ba856a9..4af654f 100644 --- a/Makefile +++ b/Makefile @@ -9,13 +9,22 @@ VLOG_FLAGS += -svinputport=compat VLOG_FLAGS += -suppress 2583 VLOG_FLAGS += +cover=sbecft +CTRL_UNIT_DIR = src/ctrl_unit +CTRL_UNIT = $(CTRL_UNIT_DIR)/cluster_icache_ctrl + Bender.lock: $(BENDER) update .bender: $(BENDER) checkout -compile.tcl: .bender +.PHONY: gen_hw +gen_hw: .bender $(CTRL_UNIT)_reg_top.sv + +$(CTRL_UNIT)_reg_top.sv: .bender $(CTRL_UNIT).hjson + python $(shell $(BENDER) path register_interface)/vendor/lowrisc_opentitan/util/regtool.py $(CTRL_UNIT).hjson -t $(CTRL_UNIT_DIR) -r + +compile.tcl: .bender Bender.yml Bender.lock $(BENDER) script vsim -t test \ --vlog-arg="$(VLOG_FLAGS)" \ > compile.tcl diff --git a/src/ctrl_unit/cluster_icache_ctrl.hjson b/src/ctrl_unit/cluster_icache_ctrl.hjson new file mode 100644 index 0000000..5286d71 --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl.hjson @@ -0,0 +1,138 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +{ + name: "cluster_icache_ctrl", + clock_primary: "clk_i", + reset_primary: "rst_ni", + bus_interfaces: [ + { protocol: "reg_iface", + direction: "device" + } + ], + + param_list: [ + { name: "NumCores", + desc: "Number of cores", + default: "8" + }, + { name: "NumAvailableCounters", + desc: "Number of available counters", + default: "44" // NumL1Events + NumCores * NumL0Events + }, + ], + + regwidth: "32", + registers: [ + { name: "enable", + desc: "", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", + name: "enable", + desc: "", + resval: 0x1 + } + ] + }, + { name: "flush", + desc: "Flush all levels of the cache", + swaccess: "rw", + hwaccess: "hrw", + hwqe: "true", + hwext: "true", + fields: [ + { bits: "0", + name: "flush", + desc: "", + resval: 0x0 + } + ] + }, + { name: "flush_l1_only", + desc: "not yet functional", + swaccess: "rw", + hwaccess: "hrw", + hwext: "true", + hwqe: "true", + fields: [ + { bits: "0", + name: "flush", + desc: "", + resval: 0x0 + } + ] + }, + { name: "sel_flush_icache", + desc: "flush specified L0 banks (and currently the complete L1)", + swaccess: "rw", + hwaccess: "hrw", + hwext: "true", + hwqe: "true", + fields: [ + { bits: "NumCores-1:0", + name: "flush", + desc: "", + resval: 0x0000_0000 + } + ] + }, + { name: "clear_counters", + desc: "Clear all performance counters", + swaccess: "rw", + hwaccess: "hrw", + hwqe: "true", + hwext: "true", + fields: [ + { bits: "0", + name: "clear", + desc: "", + resval: 0x0 + } + ] + }, + { name: "enable_counters", + desc: "Enable performance counters", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", + name: "enable", + desc: "", + resval: 0x1 + } + ] + }, + { skipto: "0x1C" }, + { name: "enable_prefetch", + desc: "Enable prefetching", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", + name: "enable", + desc: "", + resval: 0x1 + } + ] + }, + { multireg: { + name: "counters", + desc: "Performance counters", + count: "NumAvailableCounters", + cname: "id", + swaccess: "rw0c", + hwaccess: "hrw", + fields: [ + { bits: "31:0", + name: "counter", + desc: "", + resval: 0x0000_0000 + } + ] + } + }, + ], +} diff --git a/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv b/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv new file mode 100644 index 0000000..8df9fbe --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv @@ -0,0 +1,272 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package cluster_icache_ctrl_reg_pkg; + + // Param list + parameter int NumCores = 8; + parameter int NumAvailableCounters = 44; + + // Address widths within the block + parameter int BlockAw = 8; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic q; + } cluster_icache_ctrl_reg2hw_enable_reg_t; + + typedef struct packed { + logic q; + logic qe; + } cluster_icache_ctrl_reg2hw_flush_reg_t; + + typedef struct packed { + logic q; + logic qe; + } cluster_icache_ctrl_reg2hw_flush_l1_only_reg_t; + + typedef struct packed { + logic [7:0] q; + logic qe; + } cluster_icache_ctrl_reg2hw_sel_flush_icache_reg_t; + + typedef struct packed { + logic q; + logic qe; + } cluster_icache_ctrl_reg2hw_clear_counters_reg_t; + + typedef struct packed { + logic q; + } cluster_icache_ctrl_reg2hw_enable_counters_reg_t; + + typedef struct packed { + logic q; + } cluster_icache_ctrl_reg2hw_enable_prefetch_reg_t; + + typedef struct packed { + logic [31:0] q; + } cluster_icache_ctrl_reg2hw_counters_mreg_t; + + typedef struct packed { + logic d; + } cluster_icache_ctrl_hw2reg_flush_reg_t; + + typedef struct packed { + logic d; + } cluster_icache_ctrl_hw2reg_flush_l1_only_reg_t; + + typedef struct packed { + logic [7:0] d; + } cluster_icache_ctrl_hw2reg_sel_flush_icache_reg_t; + + typedef struct packed { + logic d; + } cluster_icache_ctrl_hw2reg_clear_counters_reg_t; + + typedef struct packed { + logic [31:0] d; + logic de; + } cluster_icache_ctrl_hw2reg_counters_mreg_t; + + // Register -> HW type + typedef struct packed { + cluster_icache_ctrl_reg2hw_enable_reg_t enable; // [1425:1425] + cluster_icache_ctrl_reg2hw_flush_reg_t flush; // [1424:1423] + cluster_icache_ctrl_reg2hw_flush_l1_only_reg_t flush_l1_only; // [1422:1421] + cluster_icache_ctrl_reg2hw_sel_flush_icache_reg_t sel_flush_icache; // [1420:1412] + cluster_icache_ctrl_reg2hw_clear_counters_reg_t clear_counters; // [1411:1410] + cluster_icache_ctrl_reg2hw_enable_counters_reg_t enable_counters; // [1409:1409] + cluster_icache_ctrl_reg2hw_enable_prefetch_reg_t enable_prefetch; // [1408:1408] + cluster_icache_ctrl_reg2hw_counters_mreg_t [43:0] counters; // [1407:0] + } cluster_icache_ctrl_reg2hw_t; + + // HW -> register type + typedef struct packed { + cluster_icache_ctrl_hw2reg_flush_reg_t flush; // [1462:1462] + cluster_icache_ctrl_hw2reg_flush_l1_only_reg_t flush_l1_only; // [1461:1461] + cluster_icache_ctrl_hw2reg_sel_flush_icache_reg_t sel_flush_icache; // [1460:1453] + cluster_icache_ctrl_hw2reg_clear_counters_reg_t clear_counters; // [1452:1452] + cluster_icache_ctrl_hw2reg_counters_mreg_t [43:0] counters; // [1451:0] + } cluster_icache_ctrl_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_ENABLE_OFFSET = 8'h 0; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_FLUSH_OFFSET = 8'h 4; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_FLUSH_L1_ONLY_OFFSET = 8'h 8; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_SEL_FLUSH_ICACHE_OFFSET = 8'h c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_CLEAR_COUNTERS_OFFSET = 8'h 10; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_ENABLE_COUNTERS_OFFSET = 8'h 14; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_ENABLE_PREFETCH_OFFSET = 8'h 1c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_0_OFFSET = 8'h 20; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_1_OFFSET = 8'h 24; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_2_OFFSET = 8'h 28; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_3_OFFSET = 8'h 2c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_4_OFFSET = 8'h 30; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_5_OFFSET = 8'h 34; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_6_OFFSET = 8'h 38; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_7_OFFSET = 8'h 3c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_8_OFFSET = 8'h 40; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_9_OFFSET = 8'h 44; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_10_OFFSET = 8'h 48; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_11_OFFSET = 8'h 4c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_12_OFFSET = 8'h 50; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_13_OFFSET = 8'h 54; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_14_OFFSET = 8'h 58; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_15_OFFSET = 8'h 5c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_16_OFFSET = 8'h 60; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_17_OFFSET = 8'h 64; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_18_OFFSET = 8'h 68; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_19_OFFSET = 8'h 6c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_20_OFFSET = 8'h 70; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_21_OFFSET = 8'h 74; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_22_OFFSET = 8'h 78; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_23_OFFSET = 8'h 7c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_24_OFFSET = 8'h 80; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_25_OFFSET = 8'h 84; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_26_OFFSET = 8'h 88; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_27_OFFSET = 8'h 8c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_28_OFFSET = 8'h 90; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_29_OFFSET = 8'h 94; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_30_OFFSET = 8'h 98; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_31_OFFSET = 8'h 9c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_32_OFFSET = 8'h a0; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_33_OFFSET = 8'h a4; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_34_OFFSET = 8'h a8; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_35_OFFSET = 8'h ac; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_36_OFFSET = 8'h b0; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_37_OFFSET = 8'h b4; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_38_OFFSET = 8'h b8; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_39_OFFSET = 8'h bc; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_40_OFFSET = 8'h c0; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_41_OFFSET = 8'h c4; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_42_OFFSET = 8'h c8; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_COUNTERS_43_OFFSET = 8'h cc; + + // Reset values for hwext registers and their fields + parameter logic [0:0] CLUSTER_ICACHE_CTRL_FLUSH_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_FLUSH_FLUSH_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_FLUSH_L1_ONLY_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_FLUSH_L1_ONLY_FLUSH_RESVAL = 1'h 0; + parameter logic [7:0] CLUSTER_ICACHE_CTRL_SEL_FLUSH_ICACHE_RESVAL = 8'h 0; + parameter logic [7:0] CLUSTER_ICACHE_CTRL_SEL_FLUSH_ICACHE_FLUSH_RESVAL = 8'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_CLEAR_COUNTERS_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_CLEAR_COUNTERS_CLEAR_RESVAL = 1'h 0; + + // Register index + typedef enum int { + CLUSTER_ICACHE_CTRL_ENABLE, + CLUSTER_ICACHE_CTRL_FLUSH, + CLUSTER_ICACHE_CTRL_FLUSH_L1_ONLY, + CLUSTER_ICACHE_CTRL_SEL_FLUSH_ICACHE, + CLUSTER_ICACHE_CTRL_CLEAR_COUNTERS, + CLUSTER_ICACHE_CTRL_ENABLE_COUNTERS, + CLUSTER_ICACHE_CTRL_ENABLE_PREFETCH, + CLUSTER_ICACHE_CTRL_COUNTERS_0, + CLUSTER_ICACHE_CTRL_COUNTERS_1, + CLUSTER_ICACHE_CTRL_COUNTERS_2, + CLUSTER_ICACHE_CTRL_COUNTERS_3, + CLUSTER_ICACHE_CTRL_COUNTERS_4, + CLUSTER_ICACHE_CTRL_COUNTERS_5, + CLUSTER_ICACHE_CTRL_COUNTERS_6, + CLUSTER_ICACHE_CTRL_COUNTERS_7, + CLUSTER_ICACHE_CTRL_COUNTERS_8, + CLUSTER_ICACHE_CTRL_COUNTERS_9, + CLUSTER_ICACHE_CTRL_COUNTERS_10, + CLUSTER_ICACHE_CTRL_COUNTERS_11, + CLUSTER_ICACHE_CTRL_COUNTERS_12, + CLUSTER_ICACHE_CTRL_COUNTERS_13, + CLUSTER_ICACHE_CTRL_COUNTERS_14, + CLUSTER_ICACHE_CTRL_COUNTERS_15, + CLUSTER_ICACHE_CTRL_COUNTERS_16, + CLUSTER_ICACHE_CTRL_COUNTERS_17, + CLUSTER_ICACHE_CTRL_COUNTERS_18, + CLUSTER_ICACHE_CTRL_COUNTERS_19, + CLUSTER_ICACHE_CTRL_COUNTERS_20, + CLUSTER_ICACHE_CTRL_COUNTERS_21, + CLUSTER_ICACHE_CTRL_COUNTERS_22, + CLUSTER_ICACHE_CTRL_COUNTERS_23, + CLUSTER_ICACHE_CTRL_COUNTERS_24, + CLUSTER_ICACHE_CTRL_COUNTERS_25, + CLUSTER_ICACHE_CTRL_COUNTERS_26, + CLUSTER_ICACHE_CTRL_COUNTERS_27, + CLUSTER_ICACHE_CTRL_COUNTERS_28, + CLUSTER_ICACHE_CTRL_COUNTERS_29, + CLUSTER_ICACHE_CTRL_COUNTERS_30, + CLUSTER_ICACHE_CTRL_COUNTERS_31, + CLUSTER_ICACHE_CTRL_COUNTERS_32, + CLUSTER_ICACHE_CTRL_COUNTERS_33, + CLUSTER_ICACHE_CTRL_COUNTERS_34, + CLUSTER_ICACHE_CTRL_COUNTERS_35, + CLUSTER_ICACHE_CTRL_COUNTERS_36, + CLUSTER_ICACHE_CTRL_COUNTERS_37, + CLUSTER_ICACHE_CTRL_COUNTERS_38, + CLUSTER_ICACHE_CTRL_COUNTERS_39, + CLUSTER_ICACHE_CTRL_COUNTERS_40, + CLUSTER_ICACHE_CTRL_COUNTERS_41, + CLUSTER_ICACHE_CTRL_COUNTERS_42, + CLUSTER_ICACHE_CTRL_COUNTERS_43 + } cluster_icache_ctrl_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] CLUSTER_ICACHE_CTRL_PERMIT [51] = '{ + 4'b 0001, // index[ 0] CLUSTER_ICACHE_CTRL_ENABLE + 4'b 0001, // index[ 1] CLUSTER_ICACHE_CTRL_FLUSH + 4'b 0001, // index[ 2] CLUSTER_ICACHE_CTRL_FLUSH_L1_ONLY + 4'b 0001, // index[ 3] CLUSTER_ICACHE_CTRL_SEL_FLUSH_ICACHE + 4'b 0001, // index[ 4] CLUSTER_ICACHE_CTRL_CLEAR_COUNTERS + 4'b 0001, // index[ 5] CLUSTER_ICACHE_CTRL_ENABLE_COUNTERS + 4'b 0001, // index[ 6] CLUSTER_ICACHE_CTRL_ENABLE_PREFETCH + 4'b 1111, // index[ 7] CLUSTER_ICACHE_CTRL_COUNTERS_0 + 4'b 1111, // index[ 8] CLUSTER_ICACHE_CTRL_COUNTERS_1 + 4'b 1111, // index[ 9] CLUSTER_ICACHE_CTRL_COUNTERS_2 + 4'b 1111, // index[10] CLUSTER_ICACHE_CTRL_COUNTERS_3 + 4'b 1111, // index[11] CLUSTER_ICACHE_CTRL_COUNTERS_4 + 4'b 1111, // index[12] CLUSTER_ICACHE_CTRL_COUNTERS_5 + 4'b 1111, // index[13] CLUSTER_ICACHE_CTRL_COUNTERS_6 + 4'b 1111, // index[14] CLUSTER_ICACHE_CTRL_COUNTERS_7 + 4'b 1111, // index[15] CLUSTER_ICACHE_CTRL_COUNTERS_8 + 4'b 1111, // index[16] CLUSTER_ICACHE_CTRL_COUNTERS_9 + 4'b 1111, // index[17] CLUSTER_ICACHE_CTRL_COUNTERS_10 + 4'b 1111, // index[18] CLUSTER_ICACHE_CTRL_COUNTERS_11 + 4'b 1111, // index[19] CLUSTER_ICACHE_CTRL_COUNTERS_12 + 4'b 1111, // index[20] CLUSTER_ICACHE_CTRL_COUNTERS_13 + 4'b 1111, // index[21] CLUSTER_ICACHE_CTRL_COUNTERS_14 + 4'b 1111, // index[22] CLUSTER_ICACHE_CTRL_COUNTERS_15 + 4'b 1111, // index[23] CLUSTER_ICACHE_CTRL_COUNTERS_16 + 4'b 1111, // index[24] CLUSTER_ICACHE_CTRL_COUNTERS_17 + 4'b 1111, // index[25] CLUSTER_ICACHE_CTRL_COUNTERS_18 + 4'b 1111, // index[26] CLUSTER_ICACHE_CTRL_COUNTERS_19 + 4'b 1111, // index[27] CLUSTER_ICACHE_CTRL_COUNTERS_20 + 4'b 1111, // index[28] CLUSTER_ICACHE_CTRL_COUNTERS_21 + 4'b 1111, // index[29] CLUSTER_ICACHE_CTRL_COUNTERS_22 + 4'b 1111, // index[30] CLUSTER_ICACHE_CTRL_COUNTERS_23 + 4'b 1111, // index[31] CLUSTER_ICACHE_CTRL_COUNTERS_24 + 4'b 1111, // index[32] CLUSTER_ICACHE_CTRL_COUNTERS_25 + 4'b 1111, // index[33] CLUSTER_ICACHE_CTRL_COUNTERS_26 + 4'b 1111, // index[34] CLUSTER_ICACHE_CTRL_COUNTERS_27 + 4'b 1111, // index[35] CLUSTER_ICACHE_CTRL_COUNTERS_28 + 4'b 1111, // index[36] CLUSTER_ICACHE_CTRL_COUNTERS_29 + 4'b 1111, // index[37] CLUSTER_ICACHE_CTRL_COUNTERS_30 + 4'b 1111, // index[38] CLUSTER_ICACHE_CTRL_COUNTERS_31 + 4'b 1111, // index[39] CLUSTER_ICACHE_CTRL_COUNTERS_32 + 4'b 1111, // index[40] CLUSTER_ICACHE_CTRL_COUNTERS_33 + 4'b 1111, // index[41] CLUSTER_ICACHE_CTRL_COUNTERS_34 + 4'b 1111, // index[42] CLUSTER_ICACHE_CTRL_COUNTERS_35 + 4'b 1111, // index[43] CLUSTER_ICACHE_CTRL_COUNTERS_36 + 4'b 1111, // index[44] CLUSTER_ICACHE_CTRL_COUNTERS_37 + 4'b 1111, // index[45] CLUSTER_ICACHE_CTRL_COUNTERS_38 + 4'b 1111, // index[46] CLUSTER_ICACHE_CTRL_COUNTERS_39 + 4'b 1111, // index[47] CLUSTER_ICACHE_CTRL_COUNTERS_40 + 4'b 1111, // index[48] CLUSTER_ICACHE_CTRL_COUNTERS_41 + 4'b 1111, // index[49] CLUSTER_ICACHE_CTRL_COUNTERS_42 + 4'b 1111 // index[50] CLUSTER_ICACHE_CTRL_COUNTERS_43 + }; + +endpackage + diff --git a/src/ctrl_unit/cluster_icache_ctrl_reg_top.sv b/src/ctrl_unit/cluster_icache_ctrl_reg_top.sv new file mode 100644 index 0000000..9f9d0ca --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_reg_top.sv @@ -0,0 +1,2116 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module cluster_icache_ctrl_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 8 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output cluster_icache_ctrl_reg_pkg::cluster_icache_ctrl_reg2hw_t reg2hw, // Write + input cluster_icache_ctrl_reg_pkg::cluster_icache_ctrl_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import cluster_icache_ctrl_reg_pkg::* ; + + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic enable_qs; + logic enable_wd; + logic enable_we; + logic flush_qs; + logic flush_wd; + logic flush_we; + logic flush_re; + logic flush_l1_only_qs; + logic flush_l1_only_wd; + logic flush_l1_only_we; + logic flush_l1_only_re; + logic [7:0] sel_flush_icache_qs; + logic [7:0] sel_flush_icache_wd; + logic sel_flush_icache_we; + logic sel_flush_icache_re; + logic clear_counters_qs; + logic clear_counters_wd; + logic clear_counters_we; + logic clear_counters_re; + logic enable_counters_qs; + logic enable_counters_wd; + logic enable_counters_we; + logic enable_prefetch_qs; + logic enable_prefetch_wd; + logic enable_prefetch_we; + logic [31:0] counters_0_qs; + logic [31:0] counters_0_wd; + logic counters_0_we; + logic [31:0] counters_1_qs; + logic [31:0] counters_1_wd; + logic counters_1_we; + logic [31:0] counters_2_qs; + logic [31:0] counters_2_wd; + logic counters_2_we; + logic [31:0] counters_3_qs; + logic [31:0] counters_3_wd; + logic counters_3_we; + logic [31:0] counters_4_qs; + logic [31:0] counters_4_wd; + logic counters_4_we; + logic [31:0] counters_5_qs; + logic [31:0] counters_5_wd; + logic counters_5_we; + logic [31:0] counters_6_qs; + logic [31:0] counters_6_wd; + logic counters_6_we; + logic [31:0] counters_7_qs; + logic [31:0] counters_7_wd; + logic counters_7_we; + logic [31:0] counters_8_qs; + logic [31:0] counters_8_wd; + logic counters_8_we; + logic [31:0] counters_9_qs; + logic [31:0] counters_9_wd; + logic counters_9_we; + logic [31:0] counters_10_qs; + logic [31:0] counters_10_wd; + logic counters_10_we; + logic [31:0] counters_11_qs; + logic [31:0] counters_11_wd; + logic counters_11_we; + logic [31:0] counters_12_qs; + logic [31:0] counters_12_wd; + logic counters_12_we; + logic [31:0] counters_13_qs; + logic [31:0] counters_13_wd; + logic counters_13_we; + logic [31:0] counters_14_qs; + logic [31:0] counters_14_wd; + logic counters_14_we; + logic [31:0] counters_15_qs; + logic [31:0] counters_15_wd; + logic counters_15_we; + logic [31:0] counters_16_qs; + logic [31:0] counters_16_wd; + logic counters_16_we; + logic [31:0] counters_17_qs; + logic [31:0] counters_17_wd; + logic counters_17_we; + logic [31:0] counters_18_qs; + logic [31:0] counters_18_wd; + logic counters_18_we; + logic [31:0] counters_19_qs; + logic [31:0] counters_19_wd; + logic counters_19_we; + logic [31:0] counters_20_qs; + logic [31:0] counters_20_wd; + logic counters_20_we; + logic [31:0] counters_21_qs; + logic [31:0] counters_21_wd; + logic counters_21_we; + logic [31:0] counters_22_qs; + logic [31:0] counters_22_wd; + logic counters_22_we; + logic [31:0] counters_23_qs; + logic [31:0] counters_23_wd; + logic counters_23_we; + logic [31:0] counters_24_qs; + logic [31:0] counters_24_wd; + logic counters_24_we; + logic [31:0] counters_25_qs; + logic [31:0] counters_25_wd; + logic counters_25_we; + logic [31:0] counters_26_qs; + logic [31:0] counters_26_wd; + logic counters_26_we; + logic [31:0] counters_27_qs; + logic [31:0] counters_27_wd; + logic counters_27_we; + logic [31:0] counters_28_qs; + logic [31:0] counters_28_wd; + logic counters_28_we; + logic [31:0] counters_29_qs; + logic [31:0] counters_29_wd; + logic counters_29_we; + logic [31:0] counters_30_qs; + logic [31:0] counters_30_wd; + logic counters_30_we; + logic [31:0] counters_31_qs; + logic [31:0] counters_31_wd; + logic counters_31_we; + logic [31:0] counters_32_qs; + logic [31:0] counters_32_wd; + logic counters_32_we; + logic [31:0] counters_33_qs; + logic [31:0] counters_33_wd; + logic counters_33_we; + logic [31:0] counters_34_qs; + logic [31:0] counters_34_wd; + logic counters_34_we; + logic [31:0] counters_35_qs; + logic [31:0] counters_35_wd; + logic counters_35_we; + logic [31:0] counters_36_qs; + logic [31:0] counters_36_wd; + logic counters_36_we; + logic [31:0] counters_37_qs; + logic [31:0] counters_37_wd; + logic counters_37_we; + logic [31:0] counters_38_qs; + logic [31:0] counters_38_wd; + logic counters_38_we; + logic [31:0] counters_39_qs; + logic [31:0] counters_39_wd; + logic counters_39_we; + logic [31:0] counters_40_qs; + logic [31:0] counters_40_wd; + logic counters_40_we; + logic [31:0] counters_41_qs; + logic [31:0] counters_41_wd; + logic counters_41_we; + logic [31:0] counters_42_qs; + logic [31:0] counters_42_wd; + logic counters_42_we; + logic [31:0] counters_43_qs; + logic [31:0] counters_43_wd; + logic counters_43_we; + + // Register instances + // R[enable]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h1) + ) u_enable ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (enable_we), + .wd (enable_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.enable.q ), + + // to register interface (read) + .qs (enable_qs) + ); + + + // R[flush]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_flush ( + .re (flush_re), + .we (flush_we), + .wd (flush_wd), + .d (hw2reg.flush.d), + .qre (), + .qe (reg2hw.flush.qe), + .q (reg2hw.flush.q ), + .qs (flush_qs) + ); + + + // R[flush_l1_only]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_flush_l1_only ( + .re (flush_l1_only_re), + .we (flush_l1_only_we), + .wd (flush_l1_only_wd), + .d (hw2reg.flush_l1_only.d), + .qre (), + .qe (reg2hw.flush_l1_only.qe), + .q (reg2hw.flush_l1_only.q ), + .qs (flush_l1_only_qs) + ); + + + // R[sel_flush_icache]: V(True) + + prim_subreg_ext #( + .DW (8) + ) u_sel_flush_icache ( + .re (sel_flush_icache_re), + .we (sel_flush_icache_we), + .wd (sel_flush_icache_wd), + .d (hw2reg.sel_flush_icache.d), + .qre (), + .qe (reg2hw.sel_flush_icache.qe), + .q (reg2hw.sel_flush_icache.q ), + .qs (sel_flush_icache_qs) + ); + + + // R[clear_counters]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_clear_counters ( + .re (clear_counters_re), + .we (clear_counters_we), + .wd (clear_counters_wd), + .d (hw2reg.clear_counters.d), + .qre (), + .qe (reg2hw.clear_counters.qe), + .q (reg2hw.clear_counters.q ), + .qs (clear_counters_qs) + ); + + + // R[enable_counters]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h1) + ) u_enable_counters ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (enable_counters_we), + .wd (enable_counters_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.enable_counters.q ), + + // to register interface (read) + .qs (enable_counters_qs) + ); + + + // R[enable_prefetch]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h1) + ) u_enable_prefetch ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (enable_prefetch_we), + .wd (enable_prefetch_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.enable_prefetch.q ), + + // to register interface (read) + .qs (enable_prefetch_qs) + ); + + + + // Subregister 0 of Multireg counters + // R[counters_0]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_0_we), + .wd (counters_0_wd), + + // from internal hardware + .de (hw2reg.counters[0].de), + .d (hw2reg.counters[0].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[0].q ), + + // to register interface (read) + .qs (counters_0_qs) + ); + + // Subregister 1 of Multireg counters + // R[counters_1]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_1_we), + .wd (counters_1_wd), + + // from internal hardware + .de (hw2reg.counters[1].de), + .d (hw2reg.counters[1].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[1].q ), + + // to register interface (read) + .qs (counters_1_qs) + ); + + // Subregister 2 of Multireg counters + // R[counters_2]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_2 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_2_we), + .wd (counters_2_wd), + + // from internal hardware + .de (hw2reg.counters[2].de), + .d (hw2reg.counters[2].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[2].q ), + + // to register interface (read) + .qs (counters_2_qs) + ); + + // Subregister 3 of Multireg counters + // R[counters_3]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_3 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_3_we), + .wd (counters_3_wd), + + // from internal hardware + .de (hw2reg.counters[3].de), + .d (hw2reg.counters[3].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[3].q ), + + // to register interface (read) + .qs (counters_3_qs) + ); + + // Subregister 4 of Multireg counters + // R[counters_4]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_4 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_4_we), + .wd (counters_4_wd), + + // from internal hardware + .de (hw2reg.counters[4].de), + .d (hw2reg.counters[4].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[4].q ), + + // to register interface (read) + .qs (counters_4_qs) + ); + + // Subregister 5 of Multireg counters + // R[counters_5]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_5 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_5_we), + .wd (counters_5_wd), + + // from internal hardware + .de (hw2reg.counters[5].de), + .d (hw2reg.counters[5].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[5].q ), + + // to register interface (read) + .qs (counters_5_qs) + ); + + // Subregister 6 of Multireg counters + // R[counters_6]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_6 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_6_we), + .wd (counters_6_wd), + + // from internal hardware + .de (hw2reg.counters[6].de), + .d (hw2reg.counters[6].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[6].q ), + + // to register interface (read) + .qs (counters_6_qs) + ); + + // Subregister 7 of Multireg counters + // R[counters_7]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_7 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_7_we), + .wd (counters_7_wd), + + // from internal hardware + .de (hw2reg.counters[7].de), + .d (hw2reg.counters[7].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[7].q ), + + // to register interface (read) + .qs (counters_7_qs) + ); + + // Subregister 8 of Multireg counters + // R[counters_8]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_8 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_8_we), + .wd (counters_8_wd), + + // from internal hardware + .de (hw2reg.counters[8].de), + .d (hw2reg.counters[8].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[8].q ), + + // to register interface (read) + .qs (counters_8_qs) + ); + + // Subregister 9 of Multireg counters + // R[counters_9]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_9 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_9_we), + .wd (counters_9_wd), + + // from internal hardware + .de (hw2reg.counters[9].de), + .d (hw2reg.counters[9].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[9].q ), + + // to register interface (read) + .qs (counters_9_qs) + ); + + // Subregister 10 of Multireg counters + // R[counters_10]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_10 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_10_we), + .wd (counters_10_wd), + + // from internal hardware + .de (hw2reg.counters[10].de), + .d (hw2reg.counters[10].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[10].q ), + + // to register interface (read) + .qs (counters_10_qs) + ); + + // Subregister 11 of Multireg counters + // R[counters_11]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_11 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_11_we), + .wd (counters_11_wd), + + // from internal hardware + .de (hw2reg.counters[11].de), + .d (hw2reg.counters[11].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[11].q ), + + // to register interface (read) + .qs (counters_11_qs) + ); + + // Subregister 12 of Multireg counters + // R[counters_12]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_12 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_12_we), + .wd (counters_12_wd), + + // from internal hardware + .de (hw2reg.counters[12].de), + .d (hw2reg.counters[12].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[12].q ), + + // to register interface (read) + .qs (counters_12_qs) + ); + + // Subregister 13 of Multireg counters + // R[counters_13]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_13 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_13_we), + .wd (counters_13_wd), + + // from internal hardware + .de (hw2reg.counters[13].de), + .d (hw2reg.counters[13].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[13].q ), + + // to register interface (read) + .qs (counters_13_qs) + ); + + // Subregister 14 of Multireg counters + // R[counters_14]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_14 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_14_we), + .wd (counters_14_wd), + + // from internal hardware + .de (hw2reg.counters[14].de), + .d (hw2reg.counters[14].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[14].q ), + + // to register interface (read) + .qs (counters_14_qs) + ); + + // Subregister 15 of Multireg counters + // R[counters_15]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_15 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_15_we), + .wd (counters_15_wd), + + // from internal hardware + .de (hw2reg.counters[15].de), + .d (hw2reg.counters[15].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[15].q ), + + // to register interface (read) + .qs (counters_15_qs) + ); + + // Subregister 16 of Multireg counters + // R[counters_16]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_16 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_16_we), + .wd (counters_16_wd), + + // from internal hardware + .de (hw2reg.counters[16].de), + .d (hw2reg.counters[16].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[16].q ), + + // to register interface (read) + .qs (counters_16_qs) + ); + + // Subregister 17 of Multireg counters + // R[counters_17]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_17 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_17_we), + .wd (counters_17_wd), + + // from internal hardware + .de (hw2reg.counters[17].de), + .d (hw2reg.counters[17].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[17].q ), + + // to register interface (read) + .qs (counters_17_qs) + ); + + // Subregister 18 of Multireg counters + // R[counters_18]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_18 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_18_we), + .wd (counters_18_wd), + + // from internal hardware + .de (hw2reg.counters[18].de), + .d (hw2reg.counters[18].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[18].q ), + + // to register interface (read) + .qs (counters_18_qs) + ); + + // Subregister 19 of Multireg counters + // R[counters_19]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_19 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_19_we), + .wd (counters_19_wd), + + // from internal hardware + .de (hw2reg.counters[19].de), + .d (hw2reg.counters[19].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[19].q ), + + // to register interface (read) + .qs (counters_19_qs) + ); + + // Subregister 20 of Multireg counters + // R[counters_20]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_20 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_20_we), + .wd (counters_20_wd), + + // from internal hardware + .de (hw2reg.counters[20].de), + .d (hw2reg.counters[20].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[20].q ), + + // to register interface (read) + .qs (counters_20_qs) + ); + + // Subregister 21 of Multireg counters + // R[counters_21]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_21 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_21_we), + .wd (counters_21_wd), + + // from internal hardware + .de (hw2reg.counters[21].de), + .d (hw2reg.counters[21].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[21].q ), + + // to register interface (read) + .qs (counters_21_qs) + ); + + // Subregister 22 of Multireg counters + // R[counters_22]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_22 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_22_we), + .wd (counters_22_wd), + + // from internal hardware + .de (hw2reg.counters[22].de), + .d (hw2reg.counters[22].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[22].q ), + + // to register interface (read) + .qs (counters_22_qs) + ); + + // Subregister 23 of Multireg counters + // R[counters_23]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_23 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_23_we), + .wd (counters_23_wd), + + // from internal hardware + .de (hw2reg.counters[23].de), + .d (hw2reg.counters[23].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[23].q ), + + // to register interface (read) + .qs (counters_23_qs) + ); + + // Subregister 24 of Multireg counters + // R[counters_24]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_24 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_24_we), + .wd (counters_24_wd), + + // from internal hardware + .de (hw2reg.counters[24].de), + .d (hw2reg.counters[24].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[24].q ), + + // to register interface (read) + .qs (counters_24_qs) + ); + + // Subregister 25 of Multireg counters + // R[counters_25]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_25 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_25_we), + .wd (counters_25_wd), + + // from internal hardware + .de (hw2reg.counters[25].de), + .d (hw2reg.counters[25].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[25].q ), + + // to register interface (read) + .qs (counters_25_qs) + ); + + // Subregister 26 of Multireg counters + // R[counters_26]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_26 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_26_we), + .wd (counters_26_wd), + + // from internal hardware + .de (hw2reg.counters[26].de), + .d (hw2reg.counters[26].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[26].q ), + + // to register interface (read) + .qs (counters_26_qs) + ); + + // Subregister 27 of Multireg counters + // R[counters_27]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_27 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_27_we), + .wd (counters_27_wd), + + // from internal hardware + .de (hw2reg.counters[27].de), + .d (hw2reg.counters[27].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[27].q ), + + // to register interface (read) + .qs (counters_27_qs) + ); + + // Subregister 28 of Multireg counters + // R[counters_28]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_28 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_28_we), + .wd (counters_28_wd), + + // from internal hardware + .de (hw2reg.counters[28].de), + .d (hw2reg.counters[28].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[28].q ), + + // to register interface (read) + .qs (counters_28_qs) + ); + + // Subregister 29 of Multireg counters + // R[counters_29]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_29 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_29_we), + .wd (counters_29_wd), + + // from internal hardware + .de (hw2reg.counters[29].de), + .d (hw2reg.counters[29].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[29].q ), + + // to register interface (read) + .qs (counters_29_qs) + ); + + // Subregister 30 of Multireg counters + // R[counters_30]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_30 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_30_we), + .wd (counters_30_wd), + + // from internal hardware + .de (hw2reg.counters[30].de), + .d (hw2reg.counters[30].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[30].q ), + + // to register interface (read) + .qs (counters_30_qs) + ); + + // Subregister 31 of Multireg counters + // R[counters_31]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_31 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_31_we), + .wd (counters_31_wd), + + // from internal hardware + .de (hw2reg.counters[31].de), + .d (hw2reg.counters[31].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[31].q ), + + // to register interface (read) + .qs (counters_31_qs) + ); + + // Subregister 32 of Multireg counters + // R[counters_32]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_32 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_32_we), + .wd (counters_32_wd), + + // from internal hardware + .de (hw2reg.counters[32].de), + .d (hw2reg.counters[32].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[32].q ), + + // to register interface (read) + .qs (counters_32_qs) + ); + + // Subregister 33 of Multireg counters + // R[counters_33]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_33 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_33_we), + .wd (counters_33_wd), + + // from internal hardware + .de (hw2reg.counters[33].de), + .d (hw2reg.counters[33].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[33].q ), + + // to register interface (read) + .qs (counters_33_qs) + ); + + // Subregister 34 of Multireg counters + // R[counters_34]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_34 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_34_we), + .wd (counters_34_wd), + + // from internal hardware + .de (hw2reg.counters[34].de), + .d (hw2reg.counters[34].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[34].q ), + + // to register interface (read) + .qs (counters_34_qs) + ); + + // Subregister 35 of Multireg counters + // R[counters_35]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_35 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_35_we), + .wd (counters_35_wd), + + // from internal hardware + .de (hw2reg.counters[35].de), + .d (hw2reg.counters[35].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[35].q ), + + // to register interface (read) + .qs (counters_35_qs) + ); + + // Subregister 36 of Multireg counters + // R[counters_36]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_36 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_36_we), + .wd (counters_36_wd), + + // from internal hardware + .de (hw2reg.counters[36].de), + .d (hw2reg.counters[36].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[36].q ), + + // to register interface (read) + .qs (counters_36_qs) + ); + + // Subregister 37 of Multireg counters + // R[counters_37]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_37 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_37_we), + .wd (counters_37_wd), + + // from internal hardware + .de (hw2reg.counters[37].de), + .d (hw2reg.counters[37].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[37].q ), + + // to register interface (read) + .qs (counters_37_qs) + ); + + // Subregister 38 of Multireg counters + // R[counters_38]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_38 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_38_we), + .wd (counters_38_wd), + + // from internal hardware + .de (hw2reg.counters[38].de), + .d (hw2reg.counters[38].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[38].q ), + + // to register interface (read) + .qs (counters_38_qs) + ); + + // Subregister 39 of Multireg counters + // R[counters_39]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_39 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_39_we), + .wd (counters_39_wd), + + // from internal hardware + .de (hw2reg.counters[39].de), + .d (hw2reg.counters[39].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[39].q ), + + // to register interface (read) + .qs (counters_39_qs) + ); + + // Subregister 40 of Multireg counters + // R[counters_40]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_40 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_40_we), + .wd (counters_40_wd), + + // from internal hardware + .de (hw2reg.counters[40].de), + .d (hw2reg.counters[40].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[40].q ), + + // to register interface (read) + .qs (counters_40_qs) + ); + + // Subregister 41 of Multireg counters + // R[counters_41]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_41 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_41_we), + .wd (counters_41_wd), + + // from internal hardware + .de (hw2reg.counters[41].de), + .d (hw2reg.counters[41].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[41].q ), + + // to register interface (read) + .qs (counters_41_qs) + ); + + // Subregister 42 of Multireg counters + // R[counters_42]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_42 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_42_we), + .wd (counters_42_wd), + + // from internal hardware + .de (hw2reg.counters[42].de), + .d (hw2reg.counters[42].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[42].q ), + + // to register interface (read) + .qs (counters_42_qs) + ); + + // Subregister 43 of Multireg counters + // R[counters_43]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_43 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_43_we), + .wd (counters_43_wd), + + // from internal hardware + .de (hw2reg.counters[43].de), + .d (hw2reg.counters[43].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[43].q ), + + // to register interface (read) + .qs (counters_43_qs) + ); + + + + + logic [50:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == CLUSTER_ICACHE_CTRL_ENABLE_OFFSET); + addr_hit[ 1] = (reg_addr == CLUSTER_ICACHE_CTRL_FLUSH_OFFSET); + addr_hit[ 2] = (reg_addr == CLUSTER_ICACHE_CTRL_FLUSH_L1_ONLY_OFFSET); + addr_hit[ 3] = (reg_addr == CLUSTER_ICACHE_CTRL_SEL_FLUSH_ICACHE_OFFSET); + addr_hit[ 4] = (reg_addr == CLUSTER_ICACHE_CTRL_CLEAR_COUNTERS_OFFSET); + addr_hit[ 5] = (reg_addr == CLUSTER_ICACHE_CTRL_ENABLE_COUNTERS_OFFSET); + addr_hit[ 6] = (reg_addr == CLUSTER_ICACHE_CTRL_ENABLE_PREFETCH_OFFSET); + addr_hit[ 7] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_0_OFFSET); + addr_hit[ 8] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_1_OFFSET); + addr_hit[ 9] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_2_OFFSET); + addr_hit[10] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_3_OFFSET); + addr_hit[11] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_4_OFFSET); + addr_hit[12] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_5_OFFSET); + addr_hit[13] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_6_OFFSET); + addr_hit[14] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_7_OFFSET); + addr_hit[15] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_8_OFFSET); + addr_hit[16] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_9_OFFSET); + addr_hit[17] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_10_OFFSET); + addr_hit[18] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_11_OFFSET); + addr_hit[19] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_12_OFFSET); + addr_hit[20] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_13_OFFSET); + addr_hit[21] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_14_OFFSET); + addr_hit[22] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_15_OFFSET); + addr_hit[23] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_16_OFFSET); + addr_hit[24] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_17_OFFSET); + addr_hit[25] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_18_OFFSET); + addr_hit[26] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_19_OFFSET); + addr_hit[27] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_20_OFFSET); + addr_hit[28] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_21_OFFSET); + addr_hit[29] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_22_OFFSET); + addr_hit[30] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_23_OFFSET); + addr_hit[31] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_24_OFFSET); + addr_hit[32] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_25_OFFSET); + addr_hit[33] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_26_OFFSET); + addr_hit[34] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_27_OFFSET); + addr_hit[35] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_28_OFFSET); + addr_hit[36] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_29_OFFSET); + addr_hit[37] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_30_OFFSET); + addr_hit[38] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_31_OFFSET); + addr_hit[39] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_32_OFFSET); + addr_hit[40] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_33_OFFSET); + addr_hit[41] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_34_OFFSET); + addr_hit[42] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_35_OFFSET); + addr_hit[43] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_36_OFFSET); + addr_hit[44] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_37_OFFSET); + addr_hit[45] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_38_OFFSET); + addr_hit[46] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_39_OFFSET); + addr_hit[47] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_40_OFFSET); + addr_hit[48] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_41_OFFSET); + addr_hit[49] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_42_OFFSET); + addr_hit[50] = (reg_addr == CLUSTER_ICACHE_CTRL_COUNTERS_43_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(CLUSTER_ICACHE_CTRL_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(CLUSTER_ICACHE_CTRL_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(CLUSTER_ICACHE_CTRL_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(CLUSTER_ICACHE_CTRL_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(CLUSTER_ICACHE_CTRL_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(CLUSTER_ICACHE_CTRL_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(CLUSTER_ICACHE_CTRL_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(CLUSTER_ICACHE_CTRL_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(CLUSTER_ICACHE_CTRL_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(CLUSTER_ICACHE_CTRL_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(CLUSTER_ICACHE_CTRL_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(CLUSTER_ICACHE_CTRL_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(CLUSTER_ICACHE_CTRL_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(CLUSTER_ICACHE_CTRL_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(CLUSTER_ICACHE_CTRL_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(CLUSTER_ICACHE_CTRL_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(CLUSTER_ICACHE_CTRL_PERMIT[25] & ~reg_be))) | + (addr_hit[26] & (|(CLUSTER_ICACHE_CTRL_PERMIT[26] & ~reg_be))) | + (addr_hit[27] & (|(CLUSTER_ICACHE_CTRL_PERMIT[27] & ~reg_be))) | + (addr_hit[28] & (|(CLUSTER_ICACHE_CTRL_PERMIT[28] & ~reg_be))) | + (addr_hit[29] & (|(CLUSTER_ICACHE_CTRL_PERMIT[29] & ~reg_be))) | + (addr_hit[30] & (|(CLUSTER_ICACHE_CTRL_PERMIT[30] & ~reg_be))) | + (addr_hit[31] & (|(CLUSTER_ICACHE_CTRL_PERMIT[31] & ~reg_be))) | + (addr_hit[32] & (|(CLUSTER_ICACHE_CTRL_PERMIT[32] & ~reg_be))) | + (addr_hit[33] & (|(CLUSTER_ICACHE_CTRL_PERMIT[33] & ~reg_be))) | + (addr_hit[34] & (|(CLUSTER_ICACHE_CTRL_PERMIT[34] & ~reg_be))) | + (addr_hit[35] & (|(CLUSTER_ICACHE_CTRL_PERMIT[35] & ~reg_be))) | + (addr_hit[36] & (|(CLUSTER_ICACHE_CTRL_PERMIT[36] & ~reg_be))) | + (addr_hit[37] & (|(CLUSTER_ICACHE_CTRL_PERMIT[37] & ~reg_be))) | + (addr_hit[38] & (|(CLUSTER_ICACHE_CTRL_PERMIT[38] & ~reg_be))) | + (addr_hit[39] & (|(CLUSTER_ICACHE_CTRL_PERMIT[39] & ~reg_be))) | + (addr_hit[40] & (|(CLUSTER_ICACHE_CTRL_PERMIT[40] & ~reg_be))) | + (addr_hit[41] & (|(CLUSTER_ICACHE_CTRL_PERMIT[41] & ~reg_be))) | + (addr_hit[42] & (|(CLUSTER_ICACHE_CTRL_PERMIT[42] & ~reg_be))) | + (addr_hit[43] & (|(CLUSTER_ICACHE_CTRL_PERMIT[43] & ~reg_be))) | + (addr_hit[44] & (|(CLUSTER_ICACHE_CTRL_PERMIT[44] & ~reg_be))) | + (addr_hit[45] & (|(CLUSTER_ICACHE_CTRL_PERMIT[45] & ~reg_be))) | + (addr_hit[46] & (|(CLUSTER_ICACHE_CTRL_PERMIT[46] & ~reg_be))) | + (addr_hit[47] & (|(CLUSTER_ICACHE_CTRL_PERMIT[47] & ~reg_be))) | + (addr_hit[48] & (|(CLUSTER_ICACHE_CTRL_PERMIT[48] & ~reg_be))) | + (addr_hit[49] & (|(CLUSTER_ICACHE_CTRL_PERMIT[49] & ~reg_be))) | + (addr_hit[50] & (|(CLUSTER_ICACHE_CTRL_PERMIT[50] & ~reg_be))))); + end + + assign enable_we = addr_hit[0] & reg_we & !reg_error; + assign enable_wd = reg_wdata[0]; + + assign flush_we = addr_hit[1] & reg_we & !reg_error; + assign flush_wd = reg_wdata[0]; + assign flush_re = addr_hit[1] & reg_re & !reg_error; + + assign flush_l1_only_we = addr_hit[2] & reg_we & !reg_error; + assign flush_l1_only_wd = reg_wdata[0]; + assign flush_l1_only_re = addr_hit[2] & reg_re & !reg_error; + + assign sel_flush_icache_we = addr_hit[3] & reg_we & !reg_error; + assign sel_flush_icache_wd = reg_wdata[7:0]; + assign sel_flush_icache_re = addr_hit[3] & reg_re & !reg_error; + + assign clear_counters_we = addr_hit[4] & reg_we & !reg_error; + assign clear_counters_wd = reg_wdata[0]; + assign clear_counters_re = addr_hit[4] & reg_re & !reg_error; + + assign enable_counters_we = addr_hit[5] & reg_we & !reg_error; + assign enable_counters_wd = reg_wdata[0]; + + assign enable_prefetch_we = addr_hit[6] & reg_we & !reg_error; + assign enable_prefetch_wd = reg_wdata[0]; + + assign counters_0_we = addr_hit[7] & reg_we & !reg_error; + assign counters_0_wd = reg_wdata[31:0]; + + assign counters_1_we = addr_hit[8] & reg_we & !reg_error; + assign counters_1_wd = reg_wdata[31:0]; + + assign counters_2_we = addr_hit[9] & reg_we & !reg_error; + assign counters_2_wd = reg_wdata[31:0]; + + assign counters_3_we = addr_hit[10] & reg_we & !reg_error; + assign counters_3_wd = reg_wdata[31:0]; + + assign counters_4_we = addr_hit[11] & reg_we & !reg_error; + assign counters_4_wd = reg_wdata[31:0]; + + assign counters_5_we = addr_hit[12] & reg_we & !reg_error; + assign counters_5_wd = reg_wdata[31:0]; + + assign counters_6_we = addr_hit[13] & reg_we & !reg_error; + assign counters_6_wd = reg_wdata[31:0]; + + assign counters_7_we = addr_hit[14] & reg_we & !reg_error; + assign counters_7_wd = reg_wdata[31:0]; + + assign counters_8_we = addr_hit[15] & reg_we & !reg_error; + assign counters_8_wd = reg_wdata[31:0]; + + assign counters_9_we = addr_hit[16] & reg_we & !reg_error; + assign counters_9_wd = reg_wdata[31:0]; + + assign counters_10_we = addr_hit[17] & reg_we & !reg_error; + assign counters_10_wd = reg_wdata[31:0]; + + assign counters_11_we = addr_hit[18] & reg_we & !reg_error; + assign counters_11_wd = reg_wdata[31:0]; + + assign counters_12_we = addr_hit[19] & reg_we & !reg_error; + assign counters_12_wd = reg_wdata[31:0]; + + assign counters_13_we = addr_hit[20] & reg_we & !reg_error; + assign counters_13_wd = reg_wdata[31:0]; + + assign counters_14_we = addr_hit[21] & reg_we & !reg_error; + assign counters_14_wd = reg_wdata[31:0]; + + assign counters_15_we = addr_hit[22] & reg_we & !reg_error; + assign counters_15_wd = reg_wdata[31:0]; + + assign counters_16_we = addr_hit[23] & reg_we & !reg_error; + assign counters_16_wd = reg_wdata[31:0]; + + assign counters_17_we = addr_hit[24] & reg_we & !reg_error; + assign counters_17_wd = reg_wdata[31:0]; + + assign counters_18_we = addr_hit[25] & reg_we & !reg_error; + assign counters_18_wd = reg_wdata[31:0]; + + assign counters_19_we = addr_hit[26] & reg_we & !reg_error; + assign counters_19_wd = reg_wdata[31:0]; + + assign counters_20_we = addr_hit[27] & reg_we & !reg_error; + assign counters_20_wd = reg_wdata[31:0]; + + assign counters_21_we = addr_hit[28] & reg_we & !reg_error; + assign counters_21_wd = reg_wdata[31:0]; + + assign counters_22_we = addr_hit[29] & reg_we & !reg_error; + assign counters_22_wd = reg_wdata[31:0]; + + assign counters_23_we = addr_hit[30] & reg_we & !reg_error; + assign counters_23_wd = reg_wdata[31:0]; + + assign counters_24_we = addr_hit[31] & reg_we & !reg_error; + assign counters_24_wd = reg_wdata[31:0]; + + assign counters_25_we = addr_hit[32] & reg_we & !reg_error; + assign counters_25_wd = reg_wdata[31:0]; + + assign counters_26_we = addr_hit[33] & reg_we & !reg_error; + assign counters_26_wd = reg_wdata[31:0]; + + assign counters_27_we = addr_hit[34] & reg_we & !reg_error; + assign counters_27_wd = reg_wdata[31:0]; + + assign counters_28_we = addr_hit[35] & reg_we & !reg_error; + assign counters_28_wd = reg_wdata[31:0]; + + assign counters_29_we = addr_hit[36] & reg_we & !reg_error; + assign counters_29_wd = reg_wdata[31:0]; + + assign counters_30_we = addr_hit[37] & reg_we & !reg_error; + assign counters_30_wd = reg_wdata[31:0]; + + assign counters_31_we = addr_hit[38] & reg_we & !reg_error; + assign counters_31_wd = reg_wdata[31:0]; + + assign counters_32_we = addr_hit[39] & reg_we & !reg_error; + assign counters_32_wd = reg_wdata[31:0]; + + assign counters_33_we = addr_hit[40] & reg_we & !reg_error; + assign counters_33_wd = reg_wdata[31:0]; + + assign counters_34_we = addr_hit[41] & reg_we & !reg_error; + assign counters_34_wd = reg_wdata[31:0]; + + assign counters_35_we = addr_hit[42] & reg_we & !reg_error; + assign counters_35_wd = reg_wdata[31:0]; + + assign counters_36_we = addr_hit[43] & reg_we & !reg_error; + assign counters_36_wd = reg_wdata[31:0]; + + assign counters_37_we = addr_hit[44] & reg_we & !reg_error; + assign counters_37_wd = reg_wdata[31:0]; + + assign counters_38_we = addr_hit[45] & reg_we & !reg_error; + assign counters_38_wd = reg_wdata[31:0]; + + assign counters_39_we = addr_hit[46] & reg_we & !reg_error; + assign counters_39_wd = reg_wdata[31:0]; + + assign counters_40_we = addr_hit[47] & reg_we & !reg_error; + assign counters_40_wd = reg_wdata[31:0]; + + assign counters_41_we = addr_hit[48] & reg_we & !reg_error; + assign counters_41_wd = reg_wdata[31:0]; + + assign counters_42_we = addr_hit[49] & reg_we & !reg_error; + assign counters_42_wd = reg_wdata[31:0]; + + assign counters_43_we = addr_hit[50] & reg_we & !reg_error; + assign counters_43_wd = reg_wdata[31:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = enable_qs; + end + + addr_hit[1]: begin + reg_rdata_next[0] = flush_qs; + end + + addr_hit[2]: begin + reg_rdata_next[0] = flush_l1_only_qs; + end + + addr_hit[3]: begin + reg_rdata_next[7:0] = sel_flush_icache_qs; + end + + addr_hit[4]: begin + reg_rdata_next[0] = clear_counters_qs; + end + + addr_hit[5]: begin + reg_rdata_next[0] = enable_counters_qs; + end + + addr_hit[6]: begin + reg_rdata_next[0] = enable_prefetch_qs; + end + + addr_hit[7]: begin + reg_rdata_next[31:0] = counters_0_qs; + end + + addr_hit[8]: begin + reg_rdata_next[31:0] = counters_1_qs; + end + + addr_hit[9]: begin + reg_rdata_next[31:0] = counters_2_qs; + end + + addr_hit[10]: begin + reg_rdata_next[31:0] = counters_3_qs; + end + + addr_hit[11]: begin + reg_rdata_next[31:0] = counters_4_qs; + end + + addr_hit[12]: begin + reg_rdata_next[31:0] = counters_5_qs; + end + + addr_hit[13]: begin + reg_rdata_next[31:0] = counters_6_qs; + end + + addr_hit[14]: begin + reg_rdata_next[31:0] = counters_7_qs; + end + + addr_hit[15]: begin + reg_rdata_next[31:0] = counters_8_qs; + end + + addr_hit[16]: begin + reg_rdata_next[31:0] = counters_9_qs; + end + + addr_hit[17]: begin + reg_rdata_next[31:0] = counters_10_qs; + end + + addr_hit[18]: begin + reg_rdata_next[31:0] = counters_11_qs; + end + + addr_hit[19]: begin + reg_rdata_next[31:0] = counters_12_qs; + end + + addr_hit[20]: begin + reg_rdata_next[31:0] = counters_13_qs; + end + + addr_hit[21]: begin + reg_rdata_next[31:0] = counters_14_qs; + end + + addr_hit[22]: begin + reg_rdata_next[31:0] = counters_15_qs; + end + + addr_hit[23]: begin + reg_rdata_next[31:0] = counters_16_qs; + end + + addr_hit[24]: begin + reg_rdata_next[31:0] = counters_17_qs; + end + + addr_hit[25]: begin + reg_rdata_next[31:0] = counters_18_qs; + end + + addr_hit[26]: begin + reg_rdata_next[31:0] = counters_19_qs; + end + + addr_hit[27]: begin + reg_rdata_next[31:0] = counters_20_qs; + end + + addr_hit[28]: begin + reg_rdata_next[31:0] = counters_21_qs; + end + + addr_hit[29]: begin + reg_rdata_next[31:0] = counters_22_qs; + end + + addr_hit[30]: begin + reg_rdata_next[31:0] = counters_23_qs; + end + + addr_hit[31]: begin + reg_rdata_next[31:0] = counters_24_qs; + end + + addr_hit[32]: begin + reg_rdata_next[31:0] = counters_25_qs; + end + + addr_hit[33]: begin + reg_rdata_next[31:0] = counters_26_qs; + end + + addr_hit[34]: begin + reg_rdata_next[31:0] = counters_27_qs; + end + + addr_hit[35]: begin + reg_rdata_next[31:0] = counters_28_qs; + end + + addr_hit[36]: begin + reg_rdata_next[31:0] = counters_29_qs; + end + + addr_hit[37]: begin + reg_rdata_next[31:0] = counters_30_qs; + end + + addr_hit[38]: begin + reg_rdata_next[31:0] = counters_31_qs; + end + + addr_hit[39]: begin + reg_rdata_next[31:0] = counters_32_qs; + end + + addr_hit[40]: begin + reg_rdata_next[31:0] = counters_33_qs; + end + + addr_hit[41]: begin + reg_rdata_next[31:0] = counters_34_qs; + end + + addr_hit[42]: begin + reg_rdata_next[31:0] = counters_35_qs; + end + + addr_hit[43]: begin + reg_rdata_next[31:0] = counters_36_qs; + end + + addr_hit[44]: begin + reg_rdata_next[31:0] = counters_37_qs; + end + + addr_hit[45]: begin + reg_rdata_next[31:0] = counters_38_qs; + end + + addr_hit[46]: begin + reg_rdata_next[31:0] = counters_39_qs; + end + + addr_hit[47]: begin + reg_rdata_next[31:0] = counters_40_qs; + end + + addr_hit[48]: begin + reg_rdata_next[31:0] = counters_41_qs; + end + + addr_hit[49]: begin + reg_rdata_next[31:0] = counters_42_qs; + end + + addr_hit[50]: begin + reg_rdata_next[31:0] = counters_43_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module cluster_icache_ctrl_reg_top_intf +#( + parameter int AW = 8, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output cluster_icache_ctrl_reg_pkg::cluster_icache_ctrl_reg2hw_t reg2hw, // Write + input cluster_icache_ctrl_reg_pkg::cluster_icache_ctrl_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + cluster_icache_ctrl_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + diff --git a/src/ctrl_unit/cluster_icache_ctrl_unit.sv b/src/ctrl_unit/cluster_icache_ctrl_unit.sv new file mode 100644 index 0000000..3c2061a --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_unit.sv @@ -0,0 +1,96 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module cluster_icache_ctrl_unit import snitch_icache_pkg::*; #( + parameter int unsigned NR_FETCH_PORTS = -1, + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + output logic enable_prefetching_o, + output logic [NR_FETCH_PORTS-1:0] flush_valid_o, + input logic [NR_FETCH_PORTS-1:0] flush_ready_i, + + input icache_l0_events_t [NR_FETCH_PORTS-1:0] l0_events_i, + input icache_l1_events_t l1_events_i +); + + import cluster_icache_ctrl_reg_pkg::*; + + initial begin + assert(5 == $bits(icache_l0_events_t)); + assert(4 == $bits(icache_l1_events_t)); + assert(NumAvailableCounters >= 4 + NR_FETCH_PORTS*5); + assert(NR_FETCH_PORTS <= NumCores); + end + + cluster_icache_ctrl_reg2hw_t reg2hw; + cluster_icache_ctrl_hw2reg_t hw2reg; + + cluster_icache_ctrl_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) i_regs ( + .clk_i, + .rst_ni, + + .reg_req_i, + .reg_rsp_o, + + .reg2hw (reg2hw), + .hw2reg (hw2reg), + .devmode_i (1'b0) + ); + + cluster_icache_ctrl_hw2reg_counters_mreg_t [NumAvailableCounters-1:0] counters_reg; + + always_comb begin : gen_counters_reg + // set up defaults - increment but not active + for (int unsigned i = 0; i < NumAvailableCounters; i++) begin + counters_reg[i].d = reg2hw.counters[i].q + 1; + counters_reg[i].de = '0; + end + + // Activate increment counters + counters_reg[0].de = reg2hw.enable_counters.q & l1_events_i.l1_miss; + counters_reg[1].de = reg2hw.enable_counters.q & l1_events_i.l1_hit; + counters_reg[2].de = reg2hw.enable_counters.q & l1_events_i.l1_stall; + counters_reg[3].de = reg2hw.enable_counters.q & l1_events_i.l1_handler_stall; + + for (int unsigned i = 0; i < NR_FETCH_PORTS; i++) begin + counters_reg[4 + i*5 + 0].de = reg2hw.enable_counters.q & l0_events_i[i].l0_miss; + counters_reg[4 + i*5 + 1].de = reg2hw.enable_counters.q & l0_events_i[i].l0_hit; + counters_reg[4 + i*5 + 2].de = reg2hw.enable_counters.q & l0_events_i[i].l0_prefetch; + counters_reg[4 + i*5 + 3].de = reg2hw.enable_counters.q & l0_events_i[i].l0_double_hit; + counters_reg[4 + i*5 + 4].de = reg2hw.enable_counters.q & l0_events_i[i].l0_stall; + end + + // Clear on global clear signal + if (reg2hw.clear_counters.q) begin + for (int unsigned i = 0; i < NumAvailableCounters; i++) begin + counters_reg[i].d = '0; + counters_reg[i].de = '1; + end + end + end + + assign enable_prefetching_o = reg2hw.enable_prefetch.q; + assign flush_valid_o = ({NR_FETCH_PORTS{reg2hw.flush.q}} & {NR_FETCH_PORTS{reg2hw.flush.qe}}) | + (reg2hw.sel_flush_icache.q[NR_FETCH_PORTS-1:0] & + {NR_FETCH_PORTS{reg2hw.sel_flush_icache.qe}}); + + assign hw2reg.flush.d = ~|flush_ready_i; + assign hw2reg.flush_l1_only.d = '0; + assign hw2reg.sel_flush_icache.d = ~flush_ready_i; + assign hw2reg.clear_counters.d = '0; + assign hw2reg.counters = counters_reg; + +endmodule From 6afdf029a1ba1b1769fc95e64934fcd32d2e8e32 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 25 Apr 2024 15:44:39 +0200 Subject: [PATCH 2/3] Add L1 error count registers --- src/ctrl_unit/cluster_icache_ctrl.hjson | 8 ++++++++ src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv | 2 ++ src/ctrl_unit/cluster_icache_ctrl_unit.sv | 21 ++++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/ctrl_unit/cluster_icache_ctrl.hjson b/src/ctrl_unit/cluster_icache_ctrl.hjson index 5286d71..697a7b1 100644 --- a/src/ctrl_unit/cluster_icache_ctrl.hjson +++ b/src/ctrl_unit/cluster_icache_ctrl.hjson @@ -17,6 +17,14 @@ desc: "Number of cores", default: "8" }, + { name: "NumL0Events", + desc: "Number of L0 events", + default: "5" + }, + { name: "NumL1Events", + desc: "Number of L1 events", + default: "4" + }, { name: "NumAvailableCounters", desc: "Number of available counters", default: "44" // NumL1Events + NumCores * NumL0Events diff --git a/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv b/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv index 8df9fbe..30f5ace 100644 --- a/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv +++ b/src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv @@ -8,6 +8,8 @@ package cluster_icache_ctrl_reg_pkg; // Param list parameter int NumCores = 8; + parameter int NumL0Events = 5; + parameter int NumL1Events = 4; parameter int NumAvailableCounters = 44; // Address widths within the block diff --git a/src/ctrl_unit/cluster_icache_ctrl_unit.sv b/src/ctrl_unit/cluster_icache_ctrl_unit.sv index 3c2061a..c2797a5 100644 --- a/src/ctrl_unit/cluster_icache_ctrl_unit.sv +++ b/src/ctrl_unit/cluster_icache_ctrl_unit.sv @@ -26,9 +26,9 @@ module cluster_icache_ctrl_unit import snitch_icache_pkg::*; #( import cluster_icache_ctrl_reg_pkg::*; initial begin - assert(5 == $bits(icache_l0_events_t)); - assert(4 == $bits(icache_l1_events_t)); - assert(NumAvailableCounters >= 4 + NR_FETCH_PORTS*5); + assert(NumL0Events == $bits(icache_l0_events_t)); + assert(NumL1Events == $bits(icache_l1_events_t)); + assert(NumAvailableCounters >= NumL1Events + NR_FETCH_PORTS*NumL0Events); assert(NR_FETCH_PORTS <= NumCores); end @@ -66,11 +66,16 @@ module cluster_icache_ctrl_unit import snitch_icache_pkg::*; #( counters_reg[3].de = reg2hw.enable_counters.q & l1_events_i.l1_handler_stall; for (int unsigned i = 0; i < NR_FETCH_PORTS; i++) begin - counters_reg[4 + i*5 + 0].de = reg2hw.enable_counters.q & l0_events_i[i].l0_miss; - counters_reg[4 + i*5 + 1].de = reg2hw.enable_counters.q & l0_events_i[i].l0_hit; - counters_reg[4 + i*5 + 2].de = reg2hw.enable_counters.q & l0_events_i[i].l0_prefetch; - counters_reg[4 + i*5 + 3].de = reg2hw.enable_counters.q & l0_events_i[i].l0_double_hit; - counters_reg[4 + i*5 + 4].de = reg2hw.enable_counters.q & l0_events_i[i].l0_stall; + counters_reg[NumL1Events + i*NumL0Events + 0].de = reg2hw.enable_counters.q & + l0_events_i[i].l0_miss; + counters_reg[NumL1Events + i*NumL0Events + 1].de = reg2hw.enable_counters.q & + l0_events_i[i].l0_hit; + counters_reg[NumL1Events + i*NumL0Events + 2].de = reg2hw.enable_counters.q & + l0_events_i[i].l0_prefetch; + counters_reg[NumL1Events + i*NumL0Events + 3].de = reg2hw.enable_counters.q & + l0_events_i[i].l0_double_hit; + counters_reg[NumL1Events + i*NumL0Events + 4].de = reg2hw.enable_counters.q & + l0_events_i[i].l0_stall; end // Clear on global clear signal From eb9a3d096b0e2a102a74b3de2a01173e2531d1c6 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Fri, 10 May 2024 17:04:05 +0200 Subject: [PATCH 3/3] Add ctrl_reg variant without L0 statistics --- .github/workflows/lint.yml | 2 + Bender.yml | 4 + Makefile | 6 +- .../cluster_icache_ctrl_perfctr.hjson | 146 +++++ .../cluster_icache_ctrl_perfctr_reg_pkg.sv | 154 +++++ .../cluster_icache_ctrl_perfctr_reg_top.sv | 556 ++++++++++++++++++ .../cluster_icache_ctrl_perfctr_unit.sv | 88 +++ 7 files changed, 955 insertions(+), 1 deletion(-) create mode 100644 src/ctrl_unit/cluster_icache_ctrl_perfctr.hjson create mode 100644 src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_pkg.sv create mode 100644 src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_top.sv create mode 100644 src/ctrl_unit/cluster_icache_ctrl_perfctr_unit.sv diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bb2a297..13f52d5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,6 +26,8 @@ jobs: exclude_paths: | ./src/ctrl_unit/cluster_icache_ctrl_reg_top.sv ./src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv + ./src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_top.sv + ./src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_pkg.sv github_token: ${{ secrets.GITHUB_TOKEN }} fail_on_error: true reviewdog_reporter: github-check diff --git a/Bender.yml b/Bender.yml index 75db517..1793951 100644 --- a/Bender.yml +++ b/Bender.yml @@ -43,6 +43,10 @@ sources: - src/ctrl_unit/cluster_icache_ctrl_reg_pkg.sv - src/ctrl_unit/cluster_icache_ctrl_reg_top.sv - src/ctrl_unit/cluster_icache_ctrl_unit.sv + - files: # ctrl_unit + - src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_pkg.sv + - src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_top.sv + - src/ctrl_unit/cluster_icache_ctrl_perfctr_unit.sv - target: test files: - test/snitch_icache_l0_tb.sv diff --git a/Makefile b/Makefile index 4af654f..c1e8460 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ VLOG_FLAGS += +cover=sbecft CTRL_UNIT_DIR = src/ctrl_unit CTRL_UNIT = $(CTRL_UNIT_DIR)/cluster_icache_ctrl +CTRL_UNIT_PERF = $(CTRL_UNIT_DIR)/cluster_icache_ctrl_perfctr Bender.lock: $(BENDER) update @@ -19,11 +20,14 @@ Bender.lock: $(BENDER) checkout .PHONY: gen_hw -gen_hw: .bender $(CTRL_UNIT)_reg_top.sv +gen_hw: .bender $(CTRL_UNIT)_reg_top.sv $(CTRL_UNIT_PERF)_reg_top.sv $(CTRL_UNIT)_reg_top.sv: .bender $(CTRL_UNIT).hjson python $(shell $(BENDER) path register_interface)/vendor/lowrisc_opentitan/util/regtool.py $(CTRL_UNIT).hjson -t $(CTRL_UNIT_DIR) -r +$(CTRL_UNIT_PERF)_reg_top.sv: .bender $(CTRL_UNIT_PERF).hjson + python $(shell $(BENDER) path register_interface)/vendor/lowrisc_opentitan/util/regtool.py $(CTRL_UNIT_PERF).hjson -t $(CTRL_UNIT_DIR) -r + compile.tcl: .bender Bender.yml Bender.lock $(BENDER) script vsim -t test \ --vlog-arg="$(VLOG_FLAGS)" \ diff --git a/src/ctrl_unit/cluster_icache_ctrl_perfctr.hjson b/src/ctrl_unit/cluster_icache_ctrl_perfctr.hjson new file mode 100644 index 0000000..caec36d --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_perfctr.hjson @@ -0,0 +1,146 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +{ + name: "cluster_icache_ctrl_perfctr", + clock_primary: "clk_i", + reset_primary: "rst_ni", + bus_interfaces: [ + { protocol: "reg_iface", + direction: "device" + } + ], + + param_list: [ + { name: "NumCores", + desc: "Number of cores", + default: "8" + }, + { name: "NumL0Events", + desc: "Number of L0 events", + default: "5" // Use performance counters for L0 events + }, + { name: "NumL1Events", + desc: "Number of L1 events", + default: "4" + }, + { name: "NumAvailableCounters", + desc: "Number of available counters", + default: "4" // NumL1Events + }, + ], + + regwidth: "32", + registers: [ + { name: "enable", + desc: "", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", + name: "enable", + desc: "", + resval: 0x1 + } + ] + }, + { name: "flush", + desc: "Flush all levels of the cache", + swaccess: "rw", + hwaccess: "hrw", + hwqe: "true", + hwext: "true", + fields: [ + { bits: "0", + name: "flush", + desc: "", + resval: 0x0 + } + ] + }, + { name: "flush_l1_only", + desc: "not yet functional", + swaccess: "rw", + hwaccess: "hrw", + hwext: "true", + hwqe: "true", + fields: [ + { bits: "0", + name: "flush", + desc: "", + resval: 0x0 + } + ] + }, + { name: "sel_flush_icache", + desc: "flush specified L0 banks (and currently the complete L1)", + swaccess: "rw", + hwaccess: "hrw", + hwext: "true", + hwqe: "true", + fields: [ + { bits: "NumCores-1:0", + name: "flush", + desc: "", + resval: 0x0000_0000 + } + ] + }, + { name: "clear_counters", + desc: "Clear all performance counters", + swaccess: "rw", + hwaccess: "hrw", + hwqe: "true", + hwext: "true", + fields: [ + { bits: "0", + name: "clear", + desc: "", + resval: 0x0 + } + ] + }, + { name: "enable_counters", + desc: "Enable performance counters", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", + name: "enable", + desc: "", + resval: 0x1 + } + ] + }, + { skipto: "0x1C" }, + { name: "enable_prefetch", + desc: "Enable prefetching", + swaccess: "rw", + hwaccess: "hro", + fields: [ + { bits: "0", + name: "enable", + desc: "", + resval: 0x1 + } + ] + }, + { multireg: { + name: "counters", + desc: "Performance counters", + count: "NumAvailableCounters", + cname: "id", + swaccess: "rw0c", + hwaccess: "hrw", + fields: [ + { bits: "31:0", + name: "counter", + desc: "", + resval: 0x0000_0000 + } + ] + } + }, + ], +} diff --git a/src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_pkg.sv b/src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_pkg.sv new file mode 100644 index 0000000..b836eed --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_pkg.sv @@ -0,0 +1,154 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Package auto-generated by `reggen` containing data structure + +package cluster_icache_ctrl_perfctr_reg_pkg; + + // Param list + parameter int NumCores = 8; + parameter int NumL0Events = 5; + parameter int NumL1Events = 4; + parameter int NumAvailableCounters = 4; + + // Address widths within the block + parameter int BlockAw = 6; + + //////////////////////////// + // Typedefs for registers // + //////////////////////////// + + typedef struct packed { + logic q; + } cluster_icache_ctrl_perfctr_reg2hw_enable_reg_t; + + typedef struct packed { + logic q; + logic qe; + } cluster_icache_ctrl_perfctr_reg2hw_flush_reg_t; + + typedef struct packed { + logic q; + logic qe; + } cluster_icache_ctrl_perfctr_reg2hw_flush_l1_only_reg_t; + + typedef struct packed { + logic [7:0] q; + logic qe; + } cluster_icache_ctrl_perfctr_reg2hw_sel_flush_icache_reg_t; + + typedef struct packed { + logic q; + logic qe; + } cluster_icache_ctrl_perfctr_reg2hw_clear_counters_reg_t; + + typedef struct packed { + logic q; + } cluster_icache_ctrl_perfctr_reg2hw_enable_counters_reg_t; + + typedef struct packed { + logic q; + } cluster_icache_ctrl_perfctr_reg2hw_enable_prefetch_reg_t; + + typedef struct packed { + logic [31:0] q; + } cluster_icache_ctrl_perfctr_reg2hw_counters_mreg_t; + + typedef struct packed { + logic d; + } cluster_icache_ctrl_perfctr_hw2reg_flush_reg_t; + + typedef struct packed { + logic d; + } cluster_icache_ctrl_perfctr_hw2reg_flush_l1_only_reg_t; + + typedef struct packed { + logic [7:0] d; + } cluster_icache_ctrl_perfctr_hw2reg_sel_flush_icache_reg_t; + + typedef struct packed { + logic d; + } cluster_icache_ctrl_perfctr_hw2reg_clear_counters_reg_t; + + typedef struct packed { + logic [31:0] d; + logic de; + } cluster_icache_ctrl_perfctr_hw2reg_counters_mreg_t; + + // Register -> HW type + typedef struct packed { + cluster_icache_ctrl_perfctr_reg2hw_enable_reg_t enable; // [145:145] + cluster_icache_ctrl_perfctr_reg2hw_flush_reg_t flush; // [144:143] + cluster_icache_ctrl_perfctr_reg2hw_flush_l1_only_reg_t flush_l1_only; // [142:141] + cluster_icache_ctrl_perfctr_reg2hw_sel_flush_icache_reg_t sel_flush_icache; // [140:132] + cluster_icache_ctrl_perfctr_reg2hw_clear_counters_reg_t clear_counters; // [131:130] + cluster_icache_ctrl_perfctr_reg2hw_enable_counters_reg_t enable_counters; // [129:129] + cluster_icache_ctrl_perfctr_reg2hw_enable_prefetch_reg_t enable_prefetch; // [128:128] + cluster_icache_ctrl_perfctr_reg2hw_counters_mreg_t [3:0] counters; // [127:0] + } cluster_icache_ctrl_perfctr_reg2hw_t; + + // HW -> register type + typedef struct packed { + cluster_icache_ctrl_perfctr_hw2reg_flush_reg_t flush; // [142:142] + cluster_icache_ctrl_perfctr_hw2reg_flush_l1_only_reg_t flush_l1_only; // [141:141] + cluster_icache_ctrl_perfctr_hw2reg_sel_flush_icache_reg_t sel_flush_icache; // [140:133] + cluster_icache_ctrl_perfctr_hw2reg_clear_counters_reg_t clear_counters; // [132:132] + cluster_icache_ctrl_perfctr_hw2reg_counters_mreg_t [3:0] counters; // [131:0] + } cluster_icache_ctrl_perfctr_hw2reg_t; + + // Register offsets + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_OFFSET = 6'h 0; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_OFFSET = 6'h 4; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_L1_ONLY_OFFSET = 6'h 8; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_SEL_FLUSH_ICACHE_OFFSET = 6'h c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_CLEAR_COUNTERS_OFFSET = 6'h 10; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_COUNTERS_OFFSET = 6'h 14; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_PREFETCH_OFFSET = 6'h 1c; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_0_OFFSET = 6'h 20; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_1_OFFSET = 6'h 24; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_2_OFFSET = 6'h 28; + parameter logic [BlockAw-1:0] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_3_OFFSET = 6'h 2c; + + // Reset values for hwext registers and their fields + parameter logic [0:0] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_FLUSH_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_L1_ONLY_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_L1_ONLY_FLUSH_RESVAL = 1'h 0; + parameter logic [7:0] CLUSTER_ICACHE_CTRL_PERFCTR_SEL_FLUSH_ICACHE_RESVAL = 8'h 0; + parameter logic [7:0] CLUSTER_ICACHE_CTRL_PERFCTR_SEL_FLUSH_ICACHE_FLUSH_RESVAL = 8'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_PERFCTR_CLEAR_COUNTERS_RESVAL = 1'h 0; + parameter logic [0:0] CLUSTER_ICACHE_CTRL_PERFCTR_CLEAR_COUNTERS_CLEAR_RESVAL = 1'h 0; + + // Register index + typedef enum int { + CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE, + CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH, + CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_L1_ONLY, + CLUSTER_ICACHE_CTRL_PERFCTR_SEL_FLUSH_ICACHE, + CLUSTER_ICACHE_CTRL_PERFCTR_CLEAR_COUNTERS, + CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_COUNTERS, + CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_PREFETCH, + CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_0, + CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_1, + CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_2, + CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_3 + } cluster_icache_ctrl_perfctr_id_e; + + // Register width information to check illegal writes + parameter logic [3:0] CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT [11] = '{ + 4'b 0001, // index[ 0] CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE + 4'b 0001, // index[ 1] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH + 4'b 0001, // index[ 2] CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_L1_ONLY + 4'b 0001, // index[ 3] CLUSTER_ICACHE_CTRL_PERFCTR_SEL_FLUSH_ICACHE + 4'b 0001, // index[ 4] CLUSTER_ICACHE_CTRL_PERFCTR_CLEAR_COUNTERS + 4'b 0001, // index[ 5] CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_COUNTERS + 4'b 0001, // index[ 6] CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_PREFETCH + 4'b 1111, // index[ 7] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_0 + 4'b 1111, // index[ 8] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_1 + 4'b 1111, // index[ 9] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_2 + 4'b 1111 // index[10] CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_3 + }; + +endpackage + diff --git a/src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_top.sv b/src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_top.sv new file mode 100644 index 0000000..272d08a --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_perfctr_reg_top.sv @@ -0,0 +1,556 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + + +`include "common_cells/assertions.svh" + +module cluster_icache_ctrl_perfctr_reg_top #( + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic, + parameter int AW = 6 +) ( + input logic clk_i, + input logic rst_ni, + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + // To HW + output cluster_icache_ctrl_perfctr_reg_pkg::cluster_icache_ctrl_perfctr_reg2hw_t reg2hw, // Write + input cluster_icache_ctrl_perfctr_reg_pkg::cluster_icache_ctrl_perfctr_hw2reg_t hw2reg, // Read + + + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + + import cluster_icache_ctrl_perfctr_reg_pkg::* ; + + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [BlockAw-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + + // Below register interface can be changed + reg_req_t reg_intf_req; + reg_rsp_t reg_intf_rsp; + + + assign reg_intf_req = reg_req_i; + assign reg_rsp_o = reg_intf_rsp; + + + assign reg_we = reg_intf_req.valid & reg_intf_req.write; + assign reg_re = reg_intf_req.valid & ~reg_intf_req.write; + assign reg_addr = reg_intf_req.addr[BlockAw-1:0]; + assign reg_wdata = reg_intf_req.wdata; + assign reg_be = reg_intf_req.wstrb; + assign reg_intf_rsp.rdata = reg_rdata; + assign reg_intf_rsp.error = reg_error; + assign reg_intf_rsp.ready = 1'b1; + + assign reg_rdata = reg_rdata_next ; + assign reg_error = (devmode_i & addrmiss) | wr_err; + + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic enable_qs; + logic enable_wd; + logic enable_we; + logic flush_qs; + logic flush_wd; + logic flush_we; + logic flush_re; + logic flush_l1_only_qs; + logic flush_l1_only_wd; + logic flush_l1_only_we; + logic flush_l1_only_re; + logic [7:0] sel_flush_icache_qs; + logic [7:0] sel_flush_icache_wd; + logic sel_flush_icache_we; + logic sel_flush_icache_re; + logic clear_counters_qs; + logic clear_counters_wd; + logic clear_counters_we; + logic clear_counters_re; + logic enable_counters_qs; + logic enable_counters_wd; + logic enable_counters_we; + logic enable_prefetch_qs; + logic enable_prefetch_wd; + logic enable_prefetch_we; + logic [31:0] counters_0_qs; + logic [31:0] counters_0_wd; + logic counters_0_we; + logic [31:0] counters_1_qs; + logic [31:0] counters_1_wd; + logic counters_1_we; + logic [31:0] counters_2_qs; + logic [31:0] counters_2_wd; + logic counters_2_we; + logic [31:0] counters_3_qs; + logic [31:0] counters_3_wd; + logic counters_3_we; + + // Register instances + // R[enable]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h1) + ) u_enable ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (enable_we), + .wd (enable_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.enable.q ), + + // to register interface (read) + .qs (enable_qs) + ); + + + // R[flush]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_flush ( + .re (flush_re), + .we (flush_we), + .wd (flush_wd), + .d (hw2reg.flush.d), + .qre (), + .qe (reg2hw.flush.qe), + .q (reg2hw.flush.q ), + .qs (flush_qs) + ); + + + // R[flush_l1_only]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_flush_l1_only ( + .re (flush_l1_only_re), + .we (flush_l1_only_we), + .wd (flush_l1_only_wd), + .d (hw2reg.flush_l1_only.d), + .qre (), + .qe (reg2hw.flush_l1_only.qe), + .q (reg2hw.flush_l1_only.q ), + .qs (flush_l1_only_qs) + ); + + + // R[sel_flush_icache]: V(True) + + prim_subreg_ext #( + .DW (8) + ) u_sel_flush_icache ( + .re (sel_flush_icache_re), + .we (sel_flush_icache_we), + .wd (sel_flush_icache_wd), + .d (hw2reg.sel_flush_icache.d), + .qre (), + .qe (reg2hw.sel_flush_icache.qe), + .q (reg2hw.sel_flush_icache.q ), + .qs (sel_flush_icache_qs) + ); + + + // R[clear_counters]: V(True) + + prim_subreg_ext #( + .DW (1) + ) u_clear_counters ( + .re (clear_counters_re), + .we (clear_counters_we), + .wd (clear_counters_wd), + .d (hw2reg.clear_counters.d), + .qre (), + .qe (reg2hw.clear_counters.qe), + .q (reg2hw.clear_counters.q ), + .qs (clear_counters_qs) + ); + + + // R[enable_counters]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h1) + ) u_enable_counters ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (enable_counters_we), + .wd (enable_counters_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.enable_counters.q ), + + // to register interface (read) + .qs (enable_counters_qs) + ); + + + // R[enable_prefetch]: V(False) + + prim_subreg #( + .DW (1), + .SWACCESS("RW"), + .RESVAL (1'h1) + ) u_enable_prefetch ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (enable_prefetch_we), + .wd (enable_prefetch_wd), + + // from internal hardware + .de (1'b0), + .d ('0 ), + + // to internal hardware + .qe (), + .q (reg2hw.enable_prefetch.q ), + + // to register interface (read) + .qs (enable_prefetch_qs) + ); + + + + // Subregister 0 of Multireg counters + // R[counters_0]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_0 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_0_we), + .wd (counters_0_wd), + + // from internal hardware + .de (hw2reg.counters[0].de), + .d (hw2reg.counters[0].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[0].q ), + + // to register interface (read) + .qs (counters_0_qs) + ); + + // Subregister 1 of Multireg counters + // R[counters_1]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_1 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_1_we), + .wd (counters_1_wd), + + // from internal hardware + .de (hw2reg.counters[1].de), + .d (hw2reg.counters[1].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[1].q ), + + // to register interface (read) + .qs (counters_1_qs) + ); + + // Subregister 2 of Multireg counters + // R[counters_2]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_2 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_2_we), + .wd (counters_2_wd), + + // from internal hardware + .de (hw2reg.counters[2].de), + .d (hw2reg.counters[2].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[2].q ), + + // to register interface (read) + .qs (counters_2_qs) + ); + + // Subregister 3 of Multireg counters + // R[counters_3]: V(False) + + prim_subreg #( + .DW (32), + .SWACCESS("W0C"), + .RESVAL (32'h0) + ) u_counters_3 ( + .clk_i (clk_i ), + .rst_ni (rst_ni ), + + // from register interface + .we (counters_3_we), + .wd (counters_3_wd), + + // from internal hardware + .de (hw2reg.counters[3].de), + .d (hw2reg.counters[3].d ), + + // to internal hardware + .qe (), + .q (reg2hw.counters[3].q ), + + // to register interface (read) + .qs (counters_3_qs) + ); + + + + + logic [10:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_OFFSET); + addr_hit[ 1] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_OFFSET); + addr_hit[ 2] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_FLUSH_L1_ONLY_OFFSET); + addr_hit[ 3] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_SEL_FLUSH_ICACHE_OFFSET); + addr_hit[ 4] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_CLEAR_COUNTERS_OFFSET); + addr_hit[ 5] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_COUNTERS_OFFSET); + addr_hit[ 6] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_ENABLE_PREFETCH_OFFSET); + addr_hit[ 7] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_0_OFFSET); + addr_hit[ 8] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_1_OFFSET); + addr_hit[ 9] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_2_OFFSET); + addr_hit[10] = (reg_addr == CLUSTER_ICACHE_CTRL_PERFCTR_COUNTERS_3_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(CLUSTER_ICACHE_CTRL_PERFCTR_PERMIT[10] & ~reg_be))))); + end + + assign enable_we = addr_hit[0] & reg_we & !reg_error; + assign enable_wd = reg_wdata[0]; + + assign flush_we = addr_hit[1] & reg_we & !reg_error; + assign flush_wd = reg_wdata[0]; + assign flush_re = addr_hit[1] & reg_re & !reg_error; + + assign flush_l1_only_we = addr_hit[2] & reg_we & !reg_error; + assign flush_l1_only_wd = reg_wdata[0]; + assign flush_l1_only_re = addr_hit[2] & reg_re & !reg_error; + + assign sel_flush_icache_we = addr_hit[3] & reg_we & !reg_error; + assign sel_flush_icache_wd = reg_wdata[7:0]; + assign sel_flush_icache_re = addr_hit[3] & reg_re & !reg_error; + + assign clear_counters_we = addr_hit[4] & reg_we & !reg_error; + assign clear_counters_wd = reg_wdata[0]; + assign clear_counters_re = addr_hit[4] & reg_re & !reg_error; + + assign enable_counters_we = addr_hit[5] & reg_we & !reg_error; + assign enable_counters_wd = reg_wdata[0]; + + assign enable_prefetch_we = addr_hit[6] & reg_we & !reg_error; + assign enable_prefetch_wd = reg_wdata[0]; + + assign counters_0_we = addr_hit[7] & reg_we & !reg_error; + assign counters_0_wd = reg_wdata[31:0]; + + assign counters_1_we = addr_hit[8] & reg_we & !reg_error; + assign counters_1_wd = reg_wdata[31:0]; + + assign counters_2_we = addr_hit[9] & reg_we & !reg_error; + assign counters_2_wd = reg_wdata[31:0]; + + assign counters_3_we = addr_hit[10] & reg_we & !reg_error; + assign counters_3_wd = reg_wdata[31:0]; + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = enable_qs; + end + + addr_hit[1]: begin + reg_rdata_next[0] = flush_qs; + end + + addr_hit[2]: begin + reg_rdata_next[0] = flush_l1_only_qs; + end + + addr_hit[3]: begin + reg_rdata_next[7:0] = sel_flush_icache_qs; + end + + addr_hit[4]: begin + reg_rdata_next[0] = clear_counters_qs; + end + + addr_hit[5]: begin + reg_rdata_next[0] = enable_counters_qs; + end + + addr_hit[6]: begin + reg_rdata_next[0] = enable_prefetch_qs; + end + + addr_hit[7]: begin + reg_rdata_next[31:0] = counters_0_qs; + end + + addr_hit[8]: begin + reg_rdata_next[31:0] = counters_1_qs; + end + + addr_hit[9]: begin + reg_rdata_next[31:0] = counters_2_qs; + end + + addr_hit[10]: begin + reg_rdata_next[31:0] = counters_3_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit)) + +endmodule + +module cluster_icache_ctrl_perfctr_reg_top_intf +#( + parameter int AW = 6, + localparam int DW = 32 +) ( + input logic clk_i, + input logic rst_ni, + REG_BUS.in regbus_slave, + // To HW + output cluster_icache_ctrl_perfctr_reg_pkg::cluster_icache_ctrl_perfctr_reg2hw_t reg2hw, // Write + input cluster_icache_ctrl_perfctr_reg_pkg::cluster_icache_ctrl_perfctr_hw2reg_t hw2reg, // Read + // Config + input devmode_i // If 1, explicit error return for unmapped register access +); + localparam int unsigned STRB_WIDTH = DW/8; + +`include "register_interface/typedef.svh" +`include "register_interface/assign.svh" + + // Define structs for reg_bus + typedef logic [AW-1:0] addr_t; + typedef logic [DW-1:0] data_t; + typedef logic [STRB_WIDTH-1:0] strb_t; + `REG_BUS_TYPEDEF_ALL(reg_bus, addr_t, data_t, strb_t) + + reg_bus_req_t s_reg_req; + reg_bus_rsp_t s_reg_rsp; + + // Assign SV interface to structs + `REG_BUS_ASSIGN_TO_REQ(s_reg_req, regbus_slave) + `REG_BUS_ASSIGN_FROM_RSP(regbus_slave, s_reg_rsp) + + + + cluster_icache_ctrl_perfctr_reg_top #( + .reg_req_t(reg_bus_req_t), + .reg_rsp_t(reg_bus_rsp_t), + .AW(AW) + ) i_regs ( + .clk_i, + .rst_ni, + .reg_req_i(s_reg_req), + .reg_rsp_o(s_reg_rsp), + .reg2hw, // Write + .hw2reg, // Read + .devmode_i + ); + +endmodule + + diff --git a/src/ctrl_unit/cluster_icache_ctrl_perfctr_unit.sv b/src/ctrl_unit/cluster_icache_ctrl_perfctr_unit.sv new file mode 100644 index 0000000..1c6e798 --- /dev/null +++ b/src/ctrl_unit/cluster_icache_ctrl_perfctr_unit.sv @@ -0,0 +1,88 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 + +// Michael Rogenmoser + +module cluster_icache_ctrl_perfctr_unit import snitch_icache_pkg::*; #( + parameter int unsigned NR_FETCH_PORTS = -1, + parameter type reg_req_t = logic, + parameter type reg_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + input reg_req_t reg_req_i, + output reg_rsp_t reg_rsp_o, + + output logic enable_prefetching_o, + output logic [NR_FETCH_PORTS-1:0] flush_valid_o, + input logic [NR_FETCH_PORTS-1:0] flush_ready_i, + + // input icache_l0_events_t [NR_FETCH_PORTS-1:0] l0_events_i, + input icache_l1_events_t l1_events_i +); + + import cluster_icache_ctrl_perfctr_reg_pkg::*; + + initial begin + // assert(NumL0Events == $bits(icache_l0_events_t)); + assert(NumL1Events == $bits(icache_l1_events_t)); + assert(NumAvailableCounters >= NumL1Events); + assert(NR_FETCH_PORTS <= NumCores); + end + + cluster_icache_ctrl_perfctr_reg2hw_t reg2hw; + cluster_icache_ctrl_perfctr_hw2reg_t hw2reg; + + cluster_icache_ctrl_perfctr_reg_top #( + .reg_req_t(reg_req_t), + .reg_rsp_t(reg_rsp_t) + ) i_regs ( + .clk_i, + .rst_ni, + + .reg_req_i, + .reg_rsp_o, + + .reg2hw (reg2hw), + .hw2reg (hw2reg), + .devmode_i (1'b0) + ); + + cluster_icache_ctrl_perfctr_hw2reg_counters_mreg_t [NumAvailableCounters-1:0] counters_reg; + + always_comb begin : gen_counters_reg + // set up defaults - increment but not active + for (int unsigned i = 0; i < NumAvailableCounters; i++) begin + counters_reg[i].d = reg2hw.counters[i].q + 1; + counters_reg[i].de = '0; + end + + // Activate increment counters + counters_reg[0].de = reg2hw.enable_counters.q & l1_events_i.l1_miss; + counters_reg[1].de = reg2hw.enable_counters.q & l1_events_i.l1_hit; + counters_reg[2].de = reg2hw.enable_counters.q & l1_events_i.l1_stall; + counters_reg[3].de = reg2hw.enable_counters.q & l1_events_i.l1_handler_stall; + + // Clear on global clear signal + if (reg2hw.clear_counters.q) begin + for (int unsigned i = 0; i < NumAvailableCounters; i++) begin + counters_reg[i].d = '0; + counters_reg[i].de = '1; + end + end + end + + assign enable_prefetching_o = reg2hw.enable_prefetch.q; + assign flush_valid_o = ({NR_FETCH_PORTS{reg2hw.flush.q}} & {NR_FETCH_PORTS{reg2hw.flush.qe}}) | + (reg2hw.sel_flush_icache.q[NR_FETCH_PORTS-1:0] & + {NR_FETCH_PORTS{reg2hw.sel_flush_icache.qe}}); + + assign hw2reg.flush.d = ~|flush_ready_i; + assign hw2reg.flush_l1_only.d = '0; + assign hw2reg.sel_flush_icache.d = ~flush_ready_i; + assign hw2reg.clear_counters.d = '0; + assign hw2reg.counters = counters_reg; + +endmodule