[top] - Integrate clkmgr
Signed-off-by: Timothy Chen <timothytim@google.com>
[clkmgr] - Integration updates
Signed-off-by: Timothy Chen <timothytim@google.com>
[clkmgr] resolve some lint warnings and comments
Signed-off-by: Timothy Chen <timothytim@google.com>
[clkmgr] - Add hjson exclusions for csr tests
- CLK_ENALBE / CLK_HINT can only be written in directed test cases
Signed-off-by: Timothy Chen <timothytim@google.com>
[top] - Update exclusions for clkmgr and pwrmgr
- Certain clkmgr/pwrmgr must be excluded from reset tests also.
The pwrmgr register can trigger a low power entry, which kills allo
clocks in the system and does not allow the test to proceed.
- Clock enable and hint registers also have the same problem.
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/clkmgr/data/clkmgr.hjson.tpl b/hw/ip/clkmgr/data/clkmgr.hjson.tpl
index 70af9b0..b9284d9 100644
--- a/hw/ip/clkmgr/data/clkmgr.hjson.tpl
+++ b/hw/ip/clkmgr/data/clkmgr.hjson.tpl
@@ -90,6 +90,9 @@
}
% endfor
]
+ // the CLK_ENABLE register cannot be written, otherwise there is the potential clocks could be
+ // disabled and the system will hang
+ tags: ["excl:CsrAllTests:CsrExclAll"]
},
{ name: "CLK_HINTS",
@@ -116,6 +119,9 @@
}
% endfor
]
+ // the CLK_HINT register cannot be written, otherwise there is the potential clocks could be
+ // disabled and the system will hang
+ tags: ["excl:CsrAllTests:CsrExclAll"]
},
{ name: "CLK_HINTS_STATUS",
diff --git a/hw/ip/clkmgr/data/clkmgr_pkg.sv.tpl b/hw/ip/clkmgr/data/clkmgr_pkg.sv.tpl
index 62ca076..23c5eca 100644
--- a/hw/ip/clkmgr/data/clkmgr_pkg.sv.tpl
+++ b/hw/ip/clkmgr/data/clkmgr_pkg.sv.tpl
@@ -15,7 +15,7 @@
};
typedef struct packed {
-% for clk in {**ft_clks, **hint_clks, **rg_clks, **sw_clks}:
+% for clk in {**hint_clks, **rg_clks, **sw_clks}:
logic ${clk};
% endfor
diff --git a/hw/ip/pwrmgr/data/pwrmgr.hjson b/hw/ip/pwrmgr/data/pwrmgr.hjson
index 668e142..a7e48f3 100644
--- a/hw/ip/pwrmgr/data/pwrmgr.hjson
+++ b/hw/ip/pwrmgr/data/pwrmgr.hjson
@@ -140,6 +140,8 @@
'''
},
]
+ tags: [// The regwen for this reg is RO. CSR seq can't support to check this reg
+ "excl:CsrAllTests:CsrExclAll"]
},
{ bits: "4",
@@ -204,8 +206,6 @@
]
},
],
- tags: [// The regwen for this reg is RO. CSR seq can't support to check this reg
- "excl:CsrNonInitTests:CsrExclCheck"]
},
{ name: "CFG_CDC_SYNC",
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 0d54d67..be577fe 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -11,6 +11,11 @@
datawidth: "32"
clocks:
{
+ hier_paths:
+ {
+ top: clkmgr_clocks.
+ ext: ""
+ }
srcs:
[
{
@@ -30,17 +35,19 @@
[
{
name: powerup
+ src: ext
sw_cg: no
unique: no
clocks:
{
- clk_fixed_powerup: fixed
- clk_main_powerup: main
- clk_usb_48mhz_powerup: usb_48mhz
+ clk_fixed_i: fixed
+ clk_i: main
+ clk_usb_48mhz_i: usb_48mhz
}
}
{
name: trans
+ src: top
sw_cg: hint
unique: yes
clocks:
@@ -51,6 +58,7 @@
}
{
name: infra
+ src: top
sw_cg: no
unique: no
clocks:
@@ -61,6 +69,7 @@
}
{
name: secure
+ src: top
sw_cg: no
unique: no
clocks:
@@ -71,6 +80,7 @@
}
{
name: peri
+ src: top
sw_cg: yes
unique: no
clocks:
@@ -81,6 +91,7 @@
}
{
name: timers
+ src: top
sw_cg: no
unique: no
clocks:
@@ -90,6 +101,7 @@
}
{
name: proc
+ src: no
sw_cg: no
unique: no
clocks:
@@ -159,6 +171,11 @@
rst_ni: sys_fixed
}
base_addr: 0x40000000
+ clock_group: secure
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_fixed_secure
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -280,11 +297,6 @@
]
alert_list: []
scan: "false"
- clock_group: secure
- clock_connections:
- {
- clk_i: clk_fixed_secure
- }
}
{
name: gpio
@@ -299,6 +311,10 @@
rst_ni: sys_fixed
}
base_addr: 0x40010000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_fixed_peri
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -329,10 +345,6 @@
]
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_fixed_peri
- }
}
{
name: spi_device
@@ -347,6 +359,10 @@
rst_ni: spi_device
}
base_addr: 0x40020000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_fixed_peri
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -454,10 +470,6 @@
]
alert_list: []
scan: "true"
- clock_connections:
- {
- clk_i: clk_fixed_peri
- }
}
{
name: flash_ctrl
@@ -472,6 +484,10 @@
rst_ni: lc
}
base_addr: 0x40030000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_infra
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -569,10 +585,6 @@
index: -1
}
]
- clock_connections:
- {
- clk_i: clk_main_infra
- }
}
{
name: rv_timer
@@ -587,6 +599,10 @@
rst_ni: sys_fixed
}
base_addr: 0x40080000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_fixed_timers
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -603,10 +619,6 @@
]
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_fixed_timers
- }
}
{
name: aes
@@ -621,6 +633,10 @@
rst_ni: sys
}
base_addr: 0x40110000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_aes
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -630,10 +646,6 @@
interrupt_list: []
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_main_aes
- }
}
{
name: hmac
@@ -648,6 +660,10 @@
rst_ni: sys
}
base_addr: 0x40120000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_hmac
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -703,10 +719,6 @@
}
]
scan: "false"
- clock_connections:
- {
- clk_i: clk_main_hmac
- }
}
{
name: rv_plic
@@ -722,6 +734,10 @@
}
base_addr: 0x40090000
generated: "true"
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_secure
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -731,10 +747,6 @@
interrupt_list: []
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_main_secure
- }
}
{
name: pinmux
@@ -753,6 +765,11 @@
}
base_addr: 0x40070000
generated: "true"
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_secure
+ clk_aon_i: clkmgr_clocks.clk_fixed_secure
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -792,11 +809,6 @@
index: -1
}
]
- clock_connections:
- {
- clk_i: clk_main_secure
- clk_aon_i: clk_fixed_secure
- }
}
{
name: alert_handler
@@ -818,6 +830,10 @@
AccuCntDw: 16
LfsrSeed: 0x7FFFFFFF
}
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_secure
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -877,15 +893,10 @@
]
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_main_secure
- }
}
{
name: pwrmgr
type: pwrmgr
- clock: main
clock_srcs:
{
clk_i: fixed
@@ -898,7 +909,11 @@
rst_slow_ni: por
}
base_addr: 0x400A0000
- generated: "true"
+ clock_connections:
+ {
+ clk_i: clk_fixed_i
+ clk_slow_i: clk_fixed_i
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -946,11 +961,13 @@
}
{
struct: pwr_clk
- type: uni
+ type: req_rsp
name: pwr_clk
act: req
package: pwrmgr_pkg
inst_name: pwrmgr
+ width: 1
+ top_signame: pwrmgr_pwr_clk
index: -1
}
{
@@ -1001,16 +1018,10 @@
index: -1
}
]
- clock_connections:
- {
- clk_i: clk_fixed_powerup
- clk_slow_i: clk_fixed_powerup
- }
}
{
name: rstmgr
type: rstmgr
- clock: main
clock_srcs:
{
clk_i: fixed
@@ -1024,7 +1035,13 @@
rst_ni: rst_ni
}
base_addr: 0x400B0000
- generated: "true"
+ clock_connections:
+ {
+ clk_i: clk_fixed_i
+ clk_main_i: clk_i
+ clk_fixed_i: clk_fixed_i
+ clk_usb_i: clk_usb_48mhz_i
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -1088,13 +1105,86 @@
index: -1
}
]
+ }
+ {
+ name: clkmgr
+ type: clkmgr
+ clock_srcs:
+ {
+ clk_i: fixed
+ clk_main_i: main
+ clk_fixed_i: fixed
+ clk_usb_48mhz_i: usb_48mhz
+ }
+ clock_group: powerup
+ reset_connections:
+ {
+ rst_ni: por
+ rst_main_ni: por
+ rst_fixed_ni: por
+ rst_usb_48mhz_ni: por
+ }
+ base_addr: 0x400C0000
+ generated: "true"
clock_connections:
{
- clk_i: clk_fixed_powerup
- clk_main_i: clk_main_powerup
- clk_fixed_i: clk_fixed_powerup
- clk_usb_i: clk_usb_48mhz_powerup
+ clk_i: clk_fixed_i
+ clk_main_i: clk_i
+ clk_fixed_i: clk_fixed_i
+ clk_usb_48mhz_i: clk_usb_48mhz_i
}
+ size: 0x1000
+ bus_device: tlul
+ bus_host: none
+ available_input_list: []
+ available_output_list: []
+ available_inout_list: []
+ interrupt_list: []
+ alert_list: []
+ scan: "false"
+ inter_signal_list:
+ [
+ {
+ struct: clkmgr_out
+ type: uni
+ name: clocks
+ act: req
+ package: clkmgr_pkg
+ inst_name: clkmgr
+ width: 1
+ top_signame: clkmgr_clocks
+ index: -1
+ }
+ {
+ struct: pwr_clk
+ type: req_rsp
+ name: pwr
+ act: rsp
+ inst_name: clkmgr
+ width: 1
+ package: pwrmgr_pkg
+ top_signame: pwrmgr_pwr_clk
+ index: -1
+ }
+ {
+ struct: clk_dft
+ type: uni
+ name: dft
+ act: rcv
+ package: clkmgr_pkg
+ inst_name: clkmgr
+ index: -1
+ }
+ {
+ struct: clk_hint_status
+ type: uni
+ name: status
+ act: rcv
+ package: clkmgr_pkg
+ inst_name: clkmgr
+ index: -1
+ }
+ ]
}
{
name: nmi_gen
@@ -1109,6 +1199,10 @@
rst_ni: sys
}
base_addr: 0x40140000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_main_secure
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -1168,10 +1262,6 @@
]
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_main_secure
- }
}
{
name: usbdev
@@ -1188,6 +1278,11 @@
rst_usb_48mhz_ni: usb
}
base_addr: 0x40150000
+ clock_connections:
+ {
+ clk_i: clkmgr_clocks.clk_fixed_peri
+ clk_usb_48mhz_i: clkmgr_clocks.clk_usb_48mhz_peri
+ }
size: 0x1000
bus_device: tlul
bus_host: none
@@ -1437,11 +1532,6 @@
]
alert_list: []
scan: "false"
- clock_connections:
- {
- clk_i: clk_fixed_peri
- clk_usb_48mhz_i: clk_usb_48mhz_peri
- }
}
]
memory:
@@ -1463,7 +1553,7 @@
size: 0x4000
clock_connections:
{
- clk_i: clk_main_infra
+ clk_i: clkmgr_clocks.clk_main_infra
}
}
{
@@ -1482,7 +1572,7 @@
size: 0x10000
clock_connections:
{
- clk_i: clk_main_infra
+ clk_i: clkmgr_clocks.clk_main_infra
}
}
{
@@ -1516,7 +1606,7 @@
]
clock_connections:
{
- clk_i: clk_main_infra
+ clk_i: clkmgr_clocks.clk_main_infra
}
}
]
@@ -1532,12 +1622,17 @@
[
rstmgr.pwr
]
+ pwrmgr.pwr_clk:
+ [
+ clkmgr.pwr
+ ]
}
top:
[
rstmgr.resets
rstmgr.cpu
pwrmgr.pwr_cpu
+ clkmgr.clocks
]
external: []
}
@@ -1559,8 +1654,8 @@
}
clock_connections:
{
- clk_main_i: clk_main_infra
- clk_fixed_i: clk_fixed_infra
+ clk_main_i: clkmgr_clocks.clk_main_infra
+ clk_fixed_i: clkmgr_clocks.clk_fixed_infra
}
connections:
{
@@ -1739,6 +1834,10 @@
base_addr: 0x400B0000
size_byte: 0x1000
}
+ {
+ base_addr: 0x400C0000
+ size_byte: 0x1000
+ }
]
}
{
@@ -1875,7 +1974,7 @@
}
clock_connections:
{
- clk_peri_i: clk_fixed_infra
+ clk_peri_i: clkmgr_clocks.clk_fixed_infra
}
connections:
{
@@ -1888,6 +1987,7 @@
usbdev
pwrmgr
rstmgr
+ clkmgr
]
}
nodes:
@@ -2021,6 +2121,23 @@
xbar: false
pipeline_byp: "true"
}
+ {
+ name: clkmgr
+ type: device
+ clock: clk_peri_i
+ reset: rst_peri_ni
+ pipeline: "false"
+ inst_type: clkmgr
+ addr_range:
+ [
+ {
+ base_addr: 0x400C0000
+ size_byte: 0x1000
+ }
+ ]
+ xbar: false
+ pipeline_byp: "true"
+ }
]
clock: clk_peri_i
}
@@ -3036,11 +3153,13 @@
}
{
struct: pwr_clk
- type: uni
+ type: req_rsp
name: pwr_clk
act: req
package: pwrmgr_pkg
inst_name: pwrmgr
+ width: 1
+ top_signame: pwrmgr_pwr_clk
index: -1
}
{
@@ -3142,6 +3261,46 @@
index: -1
}
{
+ struct: clkmgr_out
+ type: uni
+ name: clocks
+ act: req
+ package: clkmgr_pkg
+ inst_name: clkmgr
+ width: 1
+ top_signame: clkmgr_clocks
+ index: -1
+ }
+ {
+ struct: pwr_clk
+ type: req_rsp
+ name: pwr
+ act: rsp
+ inst_name: clkmgr
+ width: 1
+ package: pwrmgr_pkg
+ top_signame: pwrmgr_pwr_clk
+ index: -1
+ }
+ {
+ struct: clk_dft
+ type: uni
+ name: dft
+ act: rcv
+ package: clkmgr_pkg
+ inst_name: clkmgr
+ index: -1
+ }
+ {
+ struct: clk_hint_status
+ type: uni
+ name: status
+ act: rcv
+ package: clkmgr_pkg
+ inst_name: clkmgr
+ index: -1
+ }
+ {
struct: flash
type: req_rsp
name: flash_ctrl
@@ -3185,6 +3344,20 @@
type: req_rsp
}
{
+ package: pwrmgr_pkg
+ struct: pwr_clk_req
+ signame: pwrmgr_pwr_clk_req
+ width: 1
+ type: req_rsp
+ }
+ {
+ package: pwrmgr_pkg
+ struct: pwr_clk_rsp
+ signame: pwrmgr_pwr_clk_rsp
+ width: 1
+ type: req_rsp
+ }
+ {
package: rstmgr_pkg
struct: rstmgr_out
signame: rstmgr_resets
@@ -3205,6 +3378,13 @@
width: 1
type: uni
}
+ {
+ package: clkmgr_pkg
+ struct: clkmgr_out
+ signame: clkmgr_clocks
+ width: 1
+ type: uni
+ }
]
}
}
\ No newline at end of file
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index a2e98d2..a8cee1e 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -9,10 +9,17 @@
datawidth: "32", # 32-bit datawidth
// This is the clock data strcture of the design.
+ // The hier path refers to the clock reference path (struct / port)
+ // - The top/ext desgination follows the same scheme as inter-module
// The src key indicates the raw clock sources in the design
// The groups key indicates the various clock groupings in the design
clocks: {
+ hier_paths: {
+ top: "clkmgr_clocks.", // top level is a struct
+ ext: "", // ext is a port of the clock name
+ },
+
srcs: [
{ name: "main", freq: "100000000" }
{ name: "fixed", freq: "100000000" }
@@ -22,6 +29,10 @@
// Clock Group attributes
// name: name of group.
//
+ // src: The hierarchical source of the clock
+ // "ext" - clock is supplied from a port of the top module
+ // "top" - clock is supplied from a net inside the top module
+ //
// sw_cfg: whether software is allowed to gate the clock
// "no" - software is not allowed to gate clocks
// "yes" - software is allowed to gate clocks
@@ -38,13 +49,14 @@
// The proc group is not peripheral, and direclty hardwired
groups: [
- { name: "powerup", sw_cg: "no" }
- { name: "trans", sw_cg: "hint", unique: "yes", }
- { name: "infra", sw_cg: "no", }
- { name: "secure", sw_cg: "no" }
- { name: "peri", sw_cg: "yes", unique: "no" }
- { name: "timers", sw_cg: "no" }
+ { name: "powerup", src:"ext", sw_cg: "no" }
+ { name: "trans", src:"top", sw_cg: "hint", unique: "yes", }
+ { name: "infra", src:"top", sw_cg: "no", }
+ { name: "secure", src:"top", sw_cg: "no" }
+ { name: "peri", src:"top", sw_cg: "yes", unique: "no" }
+ { name: "timers", src:"top", sw_cg: "no" }
{ name: "proc",
+ src: "no"
sw_cg: "no"
unique: "no"
clocks: {
@@ -174,20 +186,25 @@
}
{ name: "pwrmgr",
type: "pwrmgr",
- clock: "main",
clock_srcs: {clk_i: "fixed", clk_slow_i: "fixed"},
clock_group: "powerup",
reset_connections: {rst_ni: "por", rst_slow_ni: "por"},
base_addr: "0x400A0000",
- generated: "true"
+
},
{ name: "rstmgr",
type: "rstmgr",
- clock: "main",
clock_srcs: {clk_i: "fixed", clk_main_i: "main", clk_fixed_i: "fixed", clk_usb_i: "usb_48mhz"},
clock_group: "powerup",
reset_connections: {rst_ni: "rst_ni"},
base_addr: "0x400B0000",
+ },
+ { name: "clkmgr",
+ type: "clkmgr",
+ clock_srcs: {clk_i: "fixed", clk_main_i: "main", clk_fixed_i: "fixed", clk_usb_48mhz_i: "usb_48mhz"},
+ clock_group: "powerup",
+ reset_connections: {rst_ni: "por", rst_main_ni: "por", rst_fixed_ni: "por", rst_usb_48mhz_ni: "por"},
+ base_addr: "0x400C0000",
generated: "true"
},
// dummy module to capture the alert handler escalation signals
@@ -255,12 +272,13 @@
'connect': {
'flash_ctrl.flash': ['eflash.flash_ctrl']
'pwrmgr.pwr_rst' : ['rstmgr.pwr'],
+ 'pwrmgr.pwr_clk' : ['clkmgr.pwr'],
}
// top is to connect to top net/struct.
// It defines the signal in the top and connect from the module,
// use of the signal is up to top template
- 'top': ['rstmgr.resets', 'rstmgr.cpu', 'pwrmgr.pwr_cpu'],
+ 'top': ['rstmgr.resets', 'rstmgr.cpu', 'pwrmgr.pwr_cpu', 'clkmgr.clocks'],
// ext is to create port in the top.
'external': [],
diff --git a/hw/top_earlgrey/data/top_earlgrey.sv.tpl b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
index 8d36e10..41386d4 100644
--- a/hw/top_earlgrey/data/top_earlgrey.sv.tpl
+++ b/hw/top_earlgrey/data/top_earlgrey.sv.tpl
@@ -25,7 +25,9 @@
max_sigwidth = len("{}".format(max_sigwidth))
clks_attr = top['clocks']
-
+cpu_clk = top['clocks']['hier_paths']['top'] + "clk_proc_main"
+cpu_rst = top["reset_paths"]["sys"]
+dm_rst = top["reset_paths"]["lc"]
%>\
module top_${top["name"]} #(
parameter bit IbexPipeLine = 0
@@ -131,13 +133,6 @@
% endfor
% endfor
- //clock wires declaration
-% for clock_group in clks_attr['groups']:
- % for k in clock_group['clocks']:
- logic ${k};
- % endfor
-% endfor
-
// Signals
logic [${num_mio_inputs + num_mio_inouts - 1}:0] mio2periph;
logic [${num_mio_outputs + num_mio_inouts - 1}:0] periph2mio;
@@ -218,14 +213,6 @@
${lib.im_defname(sig)} ${lib.bitarray(sig["width"],1)} ${sig["signame"]};
% endfor
- // Clock assignments
- // These assignments are temporary until the creation of the clock controller
-% for clock_group in clks_attr['groups']:
- % for k,v in clock_group['clocks'].items():
- assign ${k} = ${lib.get_clk_name(v)};
- % endfor
-% endfor
-
// Non-debug module reset == reset for everything except for the debug module
logic ndmreset_req;
@@ -250,8 +237,8 @@
.PipeLine (IbexPipeLine)
) u_rv_core_ibex (
// clock and reset
- .clk_i (clk_proc_main),
- .rst_ni (${top["reset_paths"]["sys"]}),
+ .clk_i (${cpu_clk}),
+ .rst_ni (${cpu_rst}),
.test_en_i (1'b0),
// static pinning
.hart_id_i (32'b0),
@@ -281,8 +268,8 @@
.NrHarts (1),
.IdcodeValue (JTAG_IDCODE)
) u_dm_top (
- .clk_i (clk_proc_main),
- .rst_ni (${top["reset_paths"]["lc"]}),
+ .clk_i (${cpu_clk}),
+ .rst_ni (${dm_rst}),
.testmode_i (1'b0),
.ndmreset_o (ndmreset_req),
.dmactive_o (),
diff --git a/hw/top_earlgrey/data/xbar_peri.hjson b/hw/top_earlgrey/data/xbar_peri.hjson
index 8511c44..7294aeb 100644
--- a/hw/top_earlgrey/data/xbar_peri.hjson
+++ b/hw/top_earlgrey/data/xbar_peri.hjson
@@ -53,9 +53,15 @@
clock: "clk_peri_i",
reset: "rst_peri_ni",
pipeline: "false"
+ },
+ { name: "clkmgr",
+ type: "device",
+ clock: "clk_peri_i",
+ reset: "rst_peri_ni",
+ pipeline: "false"
}
],
connections: {
- main: ["uart", "gpio", "spi_device", "rv_timer", "usbdev", "pwrmgr", "rstmgr"],
+ main: ["uart", "gpio", "spi_device", "rv_timer", "usbdev", "pwrmgr", "rstmgr", "clkmgr"],
},
}
diff --git a/hw/top_earlgrey/ip/clkmgr/clkmgr.core b/hw/top_earlgrey/ip/clkmgr/clkmgr.core
new file mode 100644
index 0000000..9e47786
--- /dev/null
+++ b/hw/top_earlgrey/ip/clkmgr/clkmgr.core
@@ -0,0 +1,25 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:top_earlgrey:clkmgr:0.1"
+description: "Clock manager component without the generated portions"
+
+filesets:
+ files_rtl:
+ depend:
+ - lowrisc:ip:tlul
+ - lowrisc:prim:all
+ - lowrisc:prim:clock_gating
+ - lowrisc:ip:pwrmgr
+ files:
+ - rtl/autogen/clkmgr_pkg.sv
+ - rtl/autogen/clkmgr_reg_pkg.sv
+ - rtl/autogen/clkmgr_reg_top.sv
+ - rtl/autogen/clkmgr.sv
+ file_type: systemVerilogSource
+
+targets:
+ default: &default_target
+ filesets:
+ - files_rtl
diff --git a/hw/top_earlgrey/ip/clkmgr/data/autogen/clkmgr.hjson b/hw/top_earlgrey/ip/clkmgr/data/autogen/clkmgr.hjson
new file mode 100644
index 0000000..8c5075f
--- /dev/null
+++ b/hw/top_earlgrey/ip/clkmgr/data/autogen/clkmgr.hjson
@@ -0,0 +1,172 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
+// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+// TODO: This module is only a draft implementation that covers most of the rstmgr
+// functoinality but is incomplete
+
+
+
+# CLKMGR register template
+#
+{
+ name: "CLKMGR",
+ clock_primary: "clk_i",
+ other_clock_list: [
+ "clk_main_i",
+ "clk_fixed_i",
+ "clk_usb_48mhz_i",
+ ],
+ reset_primary: "rst_ni",
+ other_reset_list: [
+ "rst_main_ni"
+ "rst_fixed_ni"
+ "rst_usb_48mhz_ni"
+ ]
+ bus_device: "tlul",
+ regwidth: "32",
+ param_list: [
+ { name: "NumGroups",
+ desc: "Number of clock groups",
+ type: "int",
+ default: "7",
+ local: "true"
+ },
+ ],
+
+ // Define rstmgr struct package
+ inter_signal_list: [
+ { struct: "clkmgr_out",
+ type: "uni",
+ name: "clocks",
+ act: "req",
+ package: "clkmgr_pkg",
+ },
+
+ { struct: "pwr_clk",
+ type: "req_rsp",
+ name: "pwr",
+ act: "rsp",
+ },
+
+ { struct: "clk_dft",
+ type: "uni",
+ name: "dft",
+ act: "rcv",
+ package: "clkmgr_pkg", // This should be moved elsewhere later
+ },
+
+ { struct: "clk_hint_status",
+ type: "uni",
+ name: "status",
+ act: "rcv",
+ package: "clkmgr_pkg",
+ },
+ ],
+
+
+ registers: [
+ { name: "CLK_ENABLES",
+ desc: '''
+ Clock enable for software gateable clocks.
+ These clocks are direclty controlled by software.
+ ''',
+ swaccess: "rw",
+ hwaccess: "hro",
+ fields: [
+ {
+ bits: "0",
+ name: "CLK_FIXED_PERI_EN",
+ resval: 1,
+ desc: '''
+ 0 CLK_FIXED_PERI is disabled.
+ 1 CLK_FIXED_PERI is enabled.
+ '''
+ }
+ {
+ bits: "1",
+ name: "CLK_USB_48MHZ_PERI_EN",
+ resval: 1,
+ desc: '''
+ 0 CLK_USB_48MHZ_PERI is disabled.
+ 1 CLK_USB_48MHZ_PERI is enabled.
+ '''
+ }
+ ]
+ // the CLK_ENABLE register cannot be written, otherwise there is the potential clocks could be
+ // disabled and the system will hang
+ tags: ["excl:CsrAllTests:CsrExclWrite:CsrExclWriteCheck"]
+ },
+
+ { name: "CLK_HINTS",
+ desc: '''
+ Clock hint for software gateable clocks.
+ These clocks are not fully controlled by software.
+
+ For disable, software only provides a hint, and hardware determines the final clock state based on the
+ hint and whether the block in question is idle.
+
+ ''',
+ swaccess: "rw",
+ hwaccess: "hro",
+ fields: [
+ {
+ bits: "0",
+ name: "CLK_MAIN_AES_HINT",
+ resval: 1,
+ desc: '''
+ 0 CLK_MAIN_AES can be disabled.
+ 1 CLK_MAIN_AES is enabled.
+ '''
+ }
+ {
+ bits: "1",
+ name: "CLK_MAIN_HMAC_HINT",
+ resval: 1,
+ desc: '''
+ 0 CLK_MAIN_HMAC can be disabled.
+ 1 CLK_MAIN_HMAC is enabled.
+ '''
+ }
+ ]
+ // the CLK_HINT register cannot be written, otherwise there is the potential clocks could be
+ // disabled and the system will hang
+ tags: ["excl:CsrAllTests:CsrExclWrite:CsrExclWriteCheck"]
+ },
+
+ { name: "CLK_HINTS_STATUS",
+ desc: '''
+ Since the final state of !!CLK_HINTS is not always determined by software,
+ this register provides read feedback for the current clock state.
+
+ ''',
+ swaccess: "ro",
+ hwaccess: "hwo",
+ fields: [
+ {
+ bits: "0",
+ name: "CLK_MAIN_AES_VAL",
+ resval: 1,
+ desc: '''
+ 0 CLK_MAIN_AES is disabled.
+ 1 CLK_MAIN_AES is enabled.
+ '''
+ }
+ {
+ bits: "1",
+ name: "CLK_MAIN_HMAC_VAL",
+ resval: 1,
+ desc: '''
+ 0 CLK_MAIN_HMAC is disabled.
+ 1 CLK_MAIN_HMAC is enabled.
+ '''
+ }
+ ]
+ },
+ ]
+}
diff --git a/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv
new file mode 100644
index 0000000..45cbec7
--- /dev/null
+++ b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr.sv
@@ -0,0 +1,257 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
+// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// The overall clock manager
+
+`include "prim_assert.sv"
+
+
+
+module clkmgr import clkmgr_pkg::*; (
+ // Primary module clocks
+ input clk_i,
+ input rst_ni,
+ input clk_main_i,
+ input rst_main_ni,
+ input clk_fixed_i,
+ input rst_fixed_ni,
+ input clk_usb_48mhz_i,
+ input rst_usb_48mhz_ni,
+
+ // Bus Interface
+ input tlul_pkg::tl_h2d_t tl_i,
+ output tlul_pkg::tl_d2h_t tl_o,
+
+ // pwrmgr interface
+ input pwrmgr_pkg::pwr_clk_req_t pwr_i,
+ output pwrmgr_pkg::pwr_clk_rsp_t pwr_o,
+
+ // dft interface
+ input clk_dft_t dft_i,
+
+ // idle hints
+ input clk_hint_status_t status_i,
+
+ // clock output interface
+ output clkmgr_out_t clocks_o
+
+);
+
+ ////////////////////////////////////////////////////
+ // Register Interface
+ ////////////////////////////////////////////////////
+
+ clkmgr_reg_pkg::clkmgr_reg2hw_t reg2hw;
+ clkmgr_reg_pkg::clkmgr_hw2reg_t hw2reg;
+
+ clkmgr_reg_top i_reg (
+ .clk_i,
+ .rst_ni,
+ .tl_i,
+ .tl_o,
+ .reg2hw,
+ .hw2reg,
+ .devmode_i(1'b1)
+ );
+
+
+ ////////////////////////////////////////////////////
+ // Root gating
+ ////////////////////////////////////////////////////
+
+ // the rst_ni connection below is incorrect, need to find a proper reset in the sequence to use
+ // if the clkmgr is always on, can use por synced directly
+ // if not, then need to generate something ahead of lc/sys
+
+ logic async_roots_en;
+ logic roots_en_q2, roots_en_q1, roots_en_d;
+ logic clk_main_root;
+ logic clk_main_en;
+ logic clk_fixed_root;
+ logic clk_fixed_en;
+ logic clk_usb_48mhz_root;
+ logic clk_usb_48mhz_en;
+
+ prim_clock_gating_sync i_main_cg (
+ .clk_i(clk_main_i),
+ .rst_ni(rst_main_ni),
+ .test_en_i(dft_i.test_en),
+ .async_en_i(pwr_i.ip_clk_en),
+ .en_o(clk_main_en),
+ .clk_o(clk_main_root)
+ );
+ prim_clock_gating_sync i_fixed_cg (
+ .clk_i(clk_fixed_i),
+ .rst_ni(rst_fixed_ni),
+ .test_en_i(dft_i.test_en),
+ .async_en_i(pwr_i.ip_clk_en),
+ .en_o(clk_fixed_en),
+ .clk_o(clk_fixed_root)
+ );
+ prim_clock_gating_sync i_usb_48mhz_cg (
+ .clk_i(clk_usb_48mhz_i),
+ .rst_ni(rst_usb_48mhz_ni),
+ .test_en_i(dft_i.test_en),
+ .async_en_i(pwr_i.ip_clk_en),
+ .en_o(clk_usb_48mhz_en),
+ .clk_o(clk_usb_48mhz_root)
+ );
+
+ // an async OR of all the synchronized enables
+ assign async_roots_en =
+ clk_main_en |
+ clk_fixed_en |
+ clk_usb_48mhz_en;
+
+ // Sync the OR back into clkmgr domain for feedback to pwrmgr.
+ // Since the signal is combo / converged on the other side, de-bounce
+ // the signal prior to output
+ prim_flop_2sync #(
+ .Width(1)
+ ) i_roots_en_sync (
+ .clk_i,
+ .rst_ni,
+ .d(async_roots_en),
+ .q(roots_en_d)
+ );
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ roots_en_q1 <= 1'b0;
+ roots_en_q2 <= 1'b0;
+ end else begin
+ roots_en_q1 <= roots_en_d;
+
+ if (roots_en_q1 == roots_en_d) begin
+ roots_en_q2 <= roots_en_q1;
+ end
+ end
+ end
+
+ assign pwr_o.roots_en = roots_en_q2;
+
+ ////////////////////////////////////////////////////
+ // Clocks with only root gate
+ ////////////////////////////////////////////////////
+ assign clocks_o.clk_main_infra = clk_main_root;
+ assign clocks_o.clk_fixed_infra = clk_fixed_root;
+ assign clocks_o.clk_fixed_secure = clk_fixed_root;
+ assign clocks_o.clk_main_secure = clk_main_root;
+ assign clocks_o.clk_fixed_timers = clk_fixed_root;
+ assign clocks_o.clk_proc_main = clk_main_root;
+
+ ////////////////////////////////////////////////////
+ // Software direct control group
+ ////////////////////////////////////////////////////
+
+ // the rst_ni connection below is incorrect, need to find a proper reset in the sequence to use
+ // if the clkmgr is always on, can use por synced directly
+ // if not, then need to generate something ahead of lc/sys
+ logic clk_fixed_peri_sw_en;
+ logic clk_usb_48mhz_peri_sw_en;
+
+ prim_flop_2sync #(
+ .Width(1)
+ ) i_clk_fixed_peri_sw_en_sync (
+ .clk_i(clk_fixed_i),
+ .rst_ni(rst_fixed_ni),
+ .d(reg2hw.clk_enables.clk_fixed_peri_en.q),
+ .q(clk_fixed_peri_sw_en)
+ );
+
+ prim_clock_gating i_clk_fixed_peri_cg (
+ .clk_i(clk_fixed_i),
+ .en_i(clk_fixed_peri_sw_en & clk_fixed_en),
+ .test_en_i(dft_i.test_en),
+ .clk_o(clocks_o.clk_fixed_peri)
+ );
+
+ prim_flop_2sync #(
+ .Width(1)
+ ) i_clk_usb_48mhz_peri_sw_en_sync (
+ .clk_i(clk_usb_48mhz_i),
+ .rst_ni(rst_usb_48mhz_ni),
+ .d(reg2hw.clk_enables.clk_usb_48mhz_peri_en.q),
+ .q(clk_usb_48mhz_peri_sw_en)
+ );
+
+ prim_clock_gating i_clk_usb_48mhz_peri_cg (
+ .clk_i(clk_usb_48mhz_i),
+ .en_i(clk_usb_48mhz_peri_sw_en & clk_usb_48mhz_en),
+ .test_en_i(dft_i.test_en),
+ .clk_o(clocks_o.clk_usb_48mhz_peri)
+ );
+
+
+ ////////////////////////////////////////////////////
+ // Software hint group
+ // The idle hint feedback is assumed to be synchronous to the
+ // clock target
+ ////////////////////////////////////////////////////
+
+ // the rst_ni connection below is incorrect, need to find a proper reset in the sequence to use
+ // if the clkmgr is always on, can use por synced directly
+ // if not, then need to generate something ahead of lc/sys
+
+ logic clk_main_aes_hint;
+ logic clk_main_aes_en;
+ logic clk_main_hmac_hint;
+ logic clk_main_hmac_en;
+
+ assign clk_main_aes_en = clk_main_aes_hint | ~status_i.idle[0];
+
+ prim_flop_2sync #(
+ .Width(1)
+ ) i_clk_main_aes_hint_sync (
+ .clk_i(clk_main_i),
+ .rst_ni(rst_main_ni),
+ .d(reg2hw.clk_hints.clk_main_aes_hint.q),
+ .q(clk_main_aes_hint)
+ );
+
+ prim_clock_gating i_clk_main_aes_cg (
+ .clk_i(clk_main_i),
+ .en_i(clk_main_aes_en & clk_main_en),
+ .test_en_i(dft_i.test_en),
+ .clk_o(clocks_o.clk_main_aes)
+ );
+
+ assign clk_main_hmac_en = clk_main_hmac_hint | ~status_i.idle[1];
+
+ prim_flop_2sync #(
+ .Width(1)
+ ) i_clk_main_hmac_hint_sync (
+ .clk_i(clk_main_i),
+ .rst_ni(rst_main_ni),
+ .d(reg2hw.clk_hints.clk_main_hmac_hint.q),
+ .q(clk_main_hmac_hint)
+ );
+
+ prim_clock_gating i_clk_main_hmac_cg (
+ .clk_i(clk_main_i),
+ .en_i(clk_main_hmac_en & clk_main_en),
+ .test_en_i(dft_i.test_en),
+ .clk_o(clocks_o.clk_main_hmac)
+ );
+
+
+ // state readback
+ assign hw2reg.clk_hints_status.clk_main_aes_val.de = 1'b1;
+ assign hw2reg.clk_hints_status.clk_main_aes_val.d = clk_main_aes_en;
+ assign hw2reg.clk_hints_status.clk_main_hmac_val.de = 1'b1;
+ assign hw2reg.clk_hints_status.clk_main_hmac_val.d = clk_main_hmac_en;
+
+
+ ////////////////////////////////////////////////////
+ // Assertions
+ ////////////////////////////////////////////////////
+
+
+endmodule // rstmgr
diff --git a/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_pkg.sv b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_pkg.sv
new file mode 100644
index 0000000..09dd868
--- /dev/null
+++ b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_pkg.sv
@@ -0,0 +1,42 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
+// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
+
+
+package clkmgr_pkg;
+
+ typedef struct packed {
+ logic test_en;
+ } clk_dft_t;
+
+ parameter clk_dft_t CLK_DFT_DEFAULT = '{
+ test_en: 1'b0
+ };
+
+ typedef struct packed {
+ logic clk_main_aes;
+ logic clk_main_hmac;
+ logic clk_main_infra;
+ logic clk_fixed_infra;
+ logic clk_fixed_secure;
+ logic clk_main_secure;
+ logic clk_fixed_timers;
+ logic clk_proc_main;
+ logic clk_fixed_peri;
+ logic clk_usb_48mhz_peri;
+
+ } clkmgr_out_t;
+
+ typedef struct packed {
+ logic [2-1:0] idle;
+ } clk_hint_status_t;
+
+ parameter clk_hint_status_t CLK_HINT_STATUS_DEFAULT = '{
+ idle: {2{1'b1}}
+ };
+
+
+endpackage // clkmgr_pkg
diff --git a/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_reg_pkg.sv b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_reg_pkg.sv
new file mode 100644
index 0000000..6983b10
--- /dev/null
+++ b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_reg_pkg.sv
@@ -0,0 +1,81 @@
+// 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 clkmgr_reg_pkg;
+
+ // Param list
+ parameter int NumGroups = 7;
+
+ ////////////////////////////
+ // Typedefs for registers //
+ ////////////////////////////
+ typedef struct packed {
+ struct packed {
+ logic q;
+ } clk_fixed_peri_en;
+ struct packed {
+ logic q;
+ } clk_usb_48mhz_peri_en;
+ } clkmgr_reg2hw_clk_enables_reg_t;
+
+ typedef struct packed {
+ struct packed {
+ logic q;
+ } clk_main_aes_hint;
+ struct packed {
+ logic q;
+ } clk_main_hmac_hint;
+ } clkmgr_reg2hw_clk_hints_reg_t;
+
+
+ typedef struct packed {
+ struct packed {
+ logic d;
+ logic de;
+ } clk_main_aes_val;
+ struct packed {
+ logic d;
+ logic de;
+ } clk_main_hmac_val;
+ } clkmgr_hw2reg_clk_hints_status_reg_t;
+
+
+ ///////////////////////////////////////
+ // Register to internal design logic //
+ ///////////////////////////////////////
+ typedef struct packed {
+ clkmgr_reg2hw_clk_enables_reg_t clk_enables; // [3:2]
+ clkmgr_reg2hw_clk_hints_reg_t clk_hints; // [1:0]
+ } clkmgr_reg2hw_t;
+
+ ///////////////////////////////////////
+ // Internal design logic to register //
+ ///////////////////////////////////////
+ typedef struct packed {
+ clkmgr_hw2reg_clk_hints_status_reg_t clk_hints_status; // [3:4]
+ } clkmgr_hw2reg_t;
+
+ // Register Address
+ parameter logic [3:0] CLKMGR_CLK_ENABLES_OFFSET = 4'h 0;
+ parameter logic [3:0] CLKMGR_CLK_HINTS_OFFSET = 4'h 4;
+ parameter logic [3:0] CLKMGR_CLK_HINTS_STATUS_OFFSET = 4'h 8;
+
+
+ // Register Index
+ typedef enum int {
+ CLKMGR_CLK_ENABLES,
+ CLKMGR_CLK_HINTS,
+ CLKMGR_CLK_HINTS_STATUS
+ } clkmgr_id_e;
+
+ // Register width information to check illegal writes
+ parameter logic [3:0] CLKMGR_PERMIT [3] = '{
+ 4'b 0001, // index[0] CLKMGR_CLK_ENABLES
+ 4'b 0001, // index[1] CLKMGR_CLK_HINTS
+ 4'b 0001 // index[2] CLKMGR_CLK_HINTS_STATUS
+ };
+endpackage
+
diff --git a/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_reg_top.sv b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_reg_top.sv
new file mode 100644
index 0000000..2717958
--- /dev/null
+++ b/hw/top_earlgrey/ip/clkmgr/rtl/autogen/clkmgr_reg_top.sv
@@ -0,0 +1,321 @@
+// 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 "prim_assert.sv"
+
+module clkmgr_reg_top (
+ input clk_i,
+ input rst_ni,
+
+ // Below Regster interface can be changed
+ input tlul_pkg::tl_h2d_t tl_i,
+ output tlul_pkg::tl_d2h_t tl_o,
+ // To HW
+ output clkmgr_reg_pkg::clkmgr_reg2hw_t reg2hw, // Write
+ input clkmgr_reg_pkg::clkmgr_hw2reg_t hw2reg, // Read
+
+ // Config
+ input devmode_i // If 1, explicit error return for unmapped register access
+);
+
+ import clkmgr_reg_pkg::* ;
+
+ localparam int AW = 4;
+ localparam int DW = 32;
+ localparam int DBW = DW/8; // Byte Width
+
+ // register signals
+ logic reg_we;
+ logic reg_re;
+ logic [AW-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;
+
+ tlul_pkg::tl_h2d_t tl_reg_h2d;
+ tlul_pkg::tl_d2h_t tl_reg_d2h;
+
+ assign tl_reg_h2d = tl_i;
+ assign tl_o = tl_reg_d2h;
+
+ tlul_adapter_reg #(
+ .RegAw(AW),
+ .RegDw(DW)
+ ) u_reg_if (
+ .clk_i,
+ .rst_ni,
+
+ .tl_i (tl_reg_h2d),
+ .tl_o (tl_reg_d2h),
+
+ .we_o (reg_we),
+ .re_o (reg_re),
+ .addr_o (reg_addr),
+ .wdata_o (reg_wdata),
+ .be_o (reg_be),
+ .rdata_i (reg_rdata),
+ .error_i (reg_error)
+ );
+
+ assign reg_rdata = reg_rdata_next ;
+ assign reg_error = (devmode_i & addrmiss) | wr_err ;
+
+ // Define SW related signals
+ // Format: <reg>_<field>_{wd|we|qs}
+ // or <reg>_{wd|we|qs} if field == 1 or 0
+ logic clk_enables_clk_fixed_peri_en_qs;
+ logic clk_enables_clk_fixed_peri_en_wd;
+ logic clk_enables_clk_fixed_peri_en_we;
+ logic clk_enables_clk_usb_48mhz_peri_en_qs;
+ logic clk_enables_clk_usb_48mhz_peri_en_wd;
+ logic clk_enables_clk_usb_48mhz_peri_en_we;
+ logic clk_hints_clk_main_aes_hint_qs;
+ logic clk_hints_clk_main_aes_hint_wd;
+ logic clk_hints_clk_main_aes_hint_we;
+ logic clk_hints_clk_main_hmac_hint_qs;
+ logic clk_hints_clk_main_hmac_hint_wd;
+ logic clk_hints_clk_main_hmac_hint_we;
+ logic clk_hints_status_clk_main_aes_val_qs;
+ logic clk_hints_status_clk_main_hmac_val_qs;
+
+ // Register instances
+ // R[clk_enables]: V(False)
+
+ // F[clk_fixed_peri_en]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h1)
+ ) u_clk_enables_clk_fixed_peri_en (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (clk_enables_clk_fixed_peri_en_we),
+ .wd (clk_enables_clk_fixed_peri_en_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.clk_enables.clk_fixed_peri_en.q ),
+
+ // to register interface (read)
+ .qs (clk_enables_clk_fixed_peri_en_qs)
+ );
+
+
+ // F[clk_usb_48mhz_peri_en]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h1)
+ ) u_clk_enables_clk_usb_48mhz_peri_en (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (clk_enables_clk_usb_48mhz_peri_en_we),
+ .wd (clk_enables_clk_usb_48mhz_peri_en_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.clk_enables.clk_usb_48mhz_peri_en.q ),
+
+ // to register interface (read)
+ .qs (clk_enables_clk_usb_48mhz_peri_en_qs)
+ );
+
+
+ // R[clk_hints]: V(False)
+
+ // F[clk_main_aes_hint]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h1)
+ ) u_clk_hints_clk_main_aes_hint (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (clk_hints_clk_main_aes_hint_we),
+ .wd (clk_hints_clk_main_aes_hint_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.clk_hints.clk_main_aes_hint.q ),
+
+ // to register interface (read)
+ .qs (clk_hints_clk_main_aes_hint_qs)
+ );
+
+
+ // F[clk_main_hmac_hint]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RW"),
+ .RESVAL (1'h1)
+ ) u_clk_hints_clk_main_hmac_hint (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ // from register interface
+ .we (clk_hints_clk_main_hmac_hint_we),
+ .wd (clk_hints_clk_main_hmac_hint_wd),
+
+ // from internal hardware
+ .de (1'b0),
+ .d ('0 ),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.clk_hints.clk_main_hmac_hint.q ),
+
+ // to register interface (read)
+ .qs (clk_hints_clk_main_hmac_hint_qs)
+ );
+
+
+ // R[clk_hints_status]: V(False)
+
+ // F[clk_main_aes_val]: 0:0
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RO"),
+ .RESVAL (1'h1)
+ ) u_clk_hints_status_clk_main_aes_val (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ .we (1'b0),
+ .wd ('0 ),
+
+ // from internal hardware
+ .de (hw2reg.clk_hints_status.clk_main_aes_val.de),
+ .d (hw2reg.clk_hints_status.clk_main_aes_val.d ),
+
+ // to internal hardware
+ .qe (),
+ .q (),
+
+ // to register interface (read)
+ .qs (clk_hints_status_clk_main_aes_val_qs)
+ );
+
+
+ // F[clk_main_hmac_val]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SWACCESS("RO"),
+ .RESVAL (1'h1)
+ ) u_clk_hints_status_clk_main_hmac_val (
+ .clk_i (clk_i ),
+ .rst_ni (rst_ni ),
+
+ .we (1'b0),
+ .wd ('0 ),
+
+ // from internal hardware
+ .de (hw2reg.clk_hints_status.clk_main_hmac_val.de),
+ .d (hw2reg.clk_hints_status.clk_main_hmac_val.d ),
+
+ // to internal hardware
+ .qe (),
+ .q (),
+
+ // to register interface (read)
+ .qs (clk_hints_status_clk_main_hmac_val_qs)
+ );
+
+
+
+
+ logic [2:0] addr_hit;
+ always_comb begin
+ addr_hit = '0;
+ addr_hit[0] = (reg_addr == CLKMGR_CLK_ENABLES_OFFSET);
+ addr_hit[1] = (reg_addr == CLKMGR_CLK_HINTS_OFFSET);
+ addr_hit[2] = (reg_addr == CLKMGR_CLK_HINTS_STATUS_OFFSET);
+ end
+
+ assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
+
+ // Check sub-word write is permitted
+ always_comb begin
+ wr_err = 1'b0;
+ if (addr_hit[0] && reg_we && (CLKMGR_PERMIT[0] != (CLKMGR_PERMIT[0] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[1] && reg_we && (CLKMGR_PERMIT[1] != (CLKMGR_PERMIT[1] & reg_be))) wr_err = 1'b1 ;
+ if (addr_hit[2] && reg_we && (CLKMGR_PERMIT[2] != (CLKMGR_PERMIT[2] & reg_be))) wr_err = 1'b1 ;
+ end
+
+ assign clk_enables_clk_fixed_peri_en_we = addr_hit[0] & reg_we & ~wr_err;
+ assign clk_enables_clk_fixed_peri_en_wd = reg_wdata[0];
+
+ assign clk_enables_clk_usb_48mhz_peri_en_we = addr_hit[0] & reg_we & ~wr_err;
+ assign clk_enables_clk_usb_48mhz_peri_en_wd = reg_wdata[1];
+
+ assign clk_hints_clk_main_aes_hint_we = addr_hit[1] & reg_we & ~wr_err;
+ assign clk_hints_clk_main_aes_hint_wd = reg_wdata[0];
+
+ assign clk_hints_clk_main_hmac_hint_we = addr_hit[1] & reg_we & ~wr_err;
+ assign clk_hints_clk_main_hmac_hint_wd = reg_wdata[1];
+
+
+
+ // Read data return
+ always_comb begin
+ reg_rdata_next = '0;
+ unique case (1'b1)
+ addr_hit[0]: begin
+ reg_rdata_next[0] = clk_enables_clk_fixed_peri_en_qs;
+ reg_rdata_next[1] = clk_enables_clk_usb_48mhz_peri_en_qs;
+ end
+
+ addr_hit[1]: begin
+ reg_rdata_next[0] = clk_hints_clk_main_aes_hint_qs;
+ reg_rdata_next[1] = clk_hints_clk_main_hmac_hint_qs;
+ end
+
+ addr_hit[2]: begin
+ reg_rdata_next[0] = clk_hints_status_clk_main_aes_val_qs;
+ reg_rdata_next[1] = clk_hints_status_clk_main_hmac_val_qs;
+ end
+
+ default: begin
+ reg_rdata_next = '1;
+ end
+ endcase
+ end
+
+ // Assertions for Register Interface
+ `ASSERT_PULSE(wePulse, reg_we)
+ `ASSERT_PULSE(rePulse, reg_re)
+
+ `ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o.d_valid)
+
+ `ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit))
+
+ // this is formulated as an assumption such that the FPV testbenches do disprove this
+ // property by mistake
+ `ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.parity_en == 1'b0)
+
+endmodule
diff --git a/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson b/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson
index 9f6b189..3b7c4f7 100644
--- a/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson
+++ b/hw/top_earlgrey/ip/xbar_main/data/autogen/xbar_main.gen.hjson
@@ -22,8 +22,8 @@
}
clock_connections:
{
- clk_main_i: clk_main_infra
- clk_fixed_i: clk_fixed_infra
+ clk_main_i: clkmgr_clocks.clk_main_infra
+ clk_fixed_i: clkmgr_clocks.clk_fixed_infra
}
connections:
{
@@ -184,7 +184,7 @@
}
{
base_addr: 0x400A0000
- size_byte: 0x20000
+ size_byte: 0x21000
}
{
base_addr: 0x40150000
diff --git a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv
index 4b7b733..922701c 100644
--- a/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv
+++ b/hw/top_earlgrey/ip/xbar_main/dv/autogen/xbar_env_pkg__params.sv
@@ -22,7 +22,7 @@
'{"peri", '{
'{32'h40000000, 32'h40020fff},
'{32'h40080000, 32'h40080fff},
- '{32'h400a0000, 32'h400bffff},
+ '{32'h400a0000, 32'h400c0fff},
'{32'h40150000, 32'h40150fff}
}},
'{"flash_ctrl", '{
diff --git a/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv b/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv
index 934b35b..049b428 100644
--- a/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv
+++ b/hw/top_earlgrey/ip/xbar_main/rtl/autogen/tl_main_pkg.sv
@@ -31,7 +31,7 @@
localparam logic [3:0][31:0] ADDR_MASK_PERI = {
32'h 00020fff,
32'h 00000fff,
- 32'h 0001ffff,
+ 32'h 00020fff,
32'h 00000fff
};
localparam logic [31:0] ADDR_MASK_FLASH_CTRL = 32'h 00000fff;
diff --git a/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson b/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson
index d4bffa1..781835f 100644
--- a/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson
+++ b/hw/top_earlgrey/ip/xbar_peri/data/autogen/xbar_peri.gen.hjson
@@ -20,7 +20,7 @@
}
clock_connections:
{
- clk_peri_i: clk_fixed_infra
+ clk_peri_i: clkmgr_clocks.clk_fixed_infra
}
connections:
{
@@ -33,6 +33,7 @@
usbdev
pwrmgr
rstmgr
+ clkmgr
]
}
nodes:
@@ -166,6 +167,23 @@
xbar: false
pipeline_byp: "true"
}
+ {
+ name: clkmgr
+ type: device
+ clock: clk_peri_i
+ reset: rst_peri_ni
+ pipeline: "false"
+ inst_type: clkmgr
+ addr_range:
+ [
+ {
+ base_addr: 0x400C0000
+ size_byte: 0x1000
+ }
+ ]
+ xbar: false
+ pipeline_byp: "true"
+ }
]
clock: clk_peri_i
type: xbar
diff --git a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/tb__xbar_connect.sv b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/tb__xbar_connect.sv
index 6788161..51947d7 100644
--- a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/tb__xbar_connect.sv
+++ b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/tb__xbar_connect.sv
@@ -22,3 +22,4 @@
`CONNECT_TL_DEVICE_IF(usbdev)
`CONNECT_TL_DEVICE_IF(pwrmgr)
`CONNECT_TL_DEVICE_IF(rstmgr)
+`CONNECT_TL_DEVICE_IF(clkmgr)
diff --git a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv
index c87c7a0..f4b264c 100644
--- a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv
+++ b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_env_pkg__params.sv
@@ -27,6 +27,9 @@
}},
'{"rstmgr", '{
'{32'h400b0000, 32'h400b0fff}
+ }},
+ '{"clkmgr", '{
+ '{32'h400c0000, 32'h400c0fff}
}}};
// List of Xbar hosts
@@ -38,5 +41,6 @@
"rv_timer",
"usbdev",
"pwrmgr",
- "rstmgr"}}
+ "rstmgr",
+ "clkmgr"}}
};
diff --git a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_peri_bind.sv b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_peri_bind.sv
index 79f7ba0..501dddc 100644
--- a/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_peri_bind.sv
+++ b/hw/top_earlgrey/ip/xbar_peri/dv/autogen/xbar_peri_bind.sv
@@ -56,5 +56,11 @@
.h2d (tl_rstmgr_o),
.d2h (tl_rstmgr_i)
);
+ bind xbar_peri tlul_assert #(.EndpointType("Host")) tlul_assert_device_clkmgr (
+ .clk_i (clk_peri_i),
+ .rst_ni (rst_peri_ni),
+ .h2d (tl_clkmgr_o),
+ .d2h (tl_clkmgr_i)
+ );
endmodule
diff --git a/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv b/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv
index d8d3e2e..6b86f90 100644
--- a/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv
+++ b/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/tl_peri_pkg.sv
@@ -13,6 +13,7 @@
localparam logic [31:0] ADDR_SPACE_USBDEV = 32'h 40150000;
localparam logic [31:0] ADDR_SPACE_PWRMGR = 32'h 400a0000;
localparam logic [31:0] ADDR_SPACE_RSTMGR = 32'h 400b0000;
+ localparam logic [31:0] ADDR_SPACE_CLKMGR = 32'h 400c0000;
localparam logic [31:0] ADDR_MASK_UART = 32'h 00000fff;
localparam logic [31:0] ADDR_MASK_GPIO = 32'h 00000fff;
@@ -21,9 +22,10 @@
localparam logic [31:0] ADDR_MASK_USBDEV = 32'h 00000fff;
localparam logic [31:0] ADDR_MASK_PWRMGR = 32'h 00000fff;
localparam logic [31:0] ADDR_MASK_RSTMGR = 32'h 00000fff;
+ localparam logic [31:0] ADDR_MASK_CLKMGR = 32'h 00000fff;
localparam int N_HOST = 1;
- localparam int N_DEVICE = 7;
+ localparam int N_DEVICE = 8;
typedef enum int {
TlUart = 0,
@@ -32,7 +34,8 @@
TlRvTimer = 3,
TlUsbdev = 4,
TlPwrmgr = 5,
- TlRstmgr = 6
+ TlRstmgr = 6,
+ TlClkmgr = 7
} tl_device_e;
typedef enum int {
diff --git a/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/xbar_peri.sv b/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/xbar_peri.sv
index bcff74a..bff04d4 100644
--- a/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/xbar_peri.sv
+++ b/hw/top_earlgrey/ip/xbar_peri/rtl/autogen/xbar_peri.sv
@@ -7,7 +7,7 @@
//
// Interconnect
// main
-// -> s1n_8
+// -> s1n_9
// -> uart
// -> gpio
// -> spi_device
@@ -15,6 +15,7 @@
// -> usbdev
// -> pwrmgr
// -> rstmgr
+// -> clkmgr
module xbar_peri (
input clk_peri_i,
@@ -39,6 +40,8 @@
input tlul_pkg::tl_d2h_t tl_pwrmgr_i,
output tlul_pkg::tl_h2d_t tl_rstmgr_o,
input tlul_pkg::tl_d2h_t tl_rstmgr_i,
+ output tlul_pkg::tl_h2d_t tl_clkmgr_o,
+ input tlul_pkg::tl_d2h_t tl_clkmgr_i,
input scanmode_i
);
@@ -51,65 +54,71 @@
logic unused_scanmode;
assign unused_scanmode = scanmode_i;
- tl_h2d_t tl_s1n_8_us_h2d ;
- tl_d2h_t tl_s1n_8_us_d2h ;
+ tl_h2d_t tl_s1n_9_us_h2d ;
+ tl_d2h_t tl_s1n_9_us_d2h ;
- tl_h2d_t tl_s1n_8_ds_h2d [7];
- tl_d2h_t tl_s1n_8_ds_d2h [7];
+ tl_h2d_t tl_s1n_9_ds_h2d [8];
+ tl_d2h_t tl_s1n_9_ds_d2h [8];
// Create steering signal
- logic [2:0] dev_sel_s1n_8;
+ logic [3:0] dev_sel_s1n_9;
- assign tl_uart_o = tl_s1n_8_ds_h2d[0];
- assign tl_s1n_8_ds_d2h[0] = tl_uart_i;
+ assign tl_uart_o = tl_s1n_9_ds_h2d[0];
+ assign tl_s1n_9_ds_d2h[0] = tl_uart_i;
- assign tl_gpio_o = tl_s1n_8_ds_h2d[1];
- assign tl_s1n_8_ds_d2h[1] = tl_gpio_i;
+ assign tl_gpio_o = tl_s1n_9_ds_h2d[1];
+ assign tl_s1n_9_ds_d2h[1] = tl_gpio_i;
- assign tl_spi_device_o = tl_s1n_8_ds_h2d[2];
- assign tl_s1n_8_ds_d2h[2] = tl_spi_device_i;
+ assign tl_spi_device_o = tl_s1n_9_ds_h2d[2];
+ assign tl_s1n_9_ds_d2h[2] = tl_spi_device_i;
- assign tl_rv_timer_o = tl_s1n_8_ds_h2d[3];
- assign tl_s1n_8_ds_d2h[3] = tl_rv_timer_i;
+ assign tl_rv_timer_o = tl_s1n_9_ds_h2d[3];
+ assign tl_s1n_9_ds_d2h[3] = tl_rv_timer_i;
- assign tl_usbdev_o = tl_s1n_8_ds_h2d[4];
- assign tl_s1n_8_ds_d2h[4] = tl_usbdev_i;
+ assign tl_usbdev_o = tl_s1n_9_ds_h2d[4];
+ assign tl_s1n_9_ds_d2h[4] = tl_usbdev_i;
- assign tl_pwrmgr_o = tl_s1n_8_ds_h2d[5];
- assign tl_s1n_8_ds_d2h[5] = tl_pwrmgr_i;
+ assign tl_pwrmgr_o = tl_s1n_9_ds_h2d[5];
+ assign tl_s1n_9_ds_d2h[5] = tl_pwrmgr_i;
- assign tl_rstmgr_o = tl_s1n_8_ds_h2d[6];
- assign tl_s1n_8_ds_d2h[6] = tl_rstmgr_i;
+ assign tl_rstmgr_o = tl_s1n_9_ds_h2d[6];
+ assign tl_s1n_9_ds_d2h[6] = tl_rstmgr_i;
- assign tl_s1n_8_us_h2d = tl_main_i;
- assign tl_main_o = tl_s1n_8_us_d2h;
+ assign tl_clkmgr_o = tl_s1n_9_ds_h2d[7];
+ assign tl_s1n_9_ds_d2h[7] = tl_clkmgr_i;
+
+ assign tl_s1n_9_us_h2d = tl_main_i;
+ assign tl_main_o = tl_s1n_9_us_d2h;
always_comb begin
// default steering to generate error response if address is not within the range
- dev_sel_s1n_8 = 3'd7;
- if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_UART)) == ADDR_SPACE_UART) begin
- dev_sel_s1n_8 = 3'd0;
+ dev_sel_s1n_9 = 4'd8;
+ if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_UART)) == ADDR_SPACE_UART) begin
+ dev_sel_s1n_9 = 4'd0;
- end else if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_GPIO)) == ADDR_SPACE_GPIO) begin
- dev_sel_s1n_8 = 3'd1;
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_GPIO)) == ADDR_SPACE_GPIO) begin
+ dev_sel_s1n_9 = 4'd1;
- end else if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_SPI_DEVICE)) == ADDR_SPACE_SPI_DEVICE) begin
- dev_sel_s1n_8 = 3'd2;
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_SPI_DEVICE)) == ADDR_SPACE_SPI_DEVICE) begin
+ dev_sel_s1n_9 = 4'd2;
- end else if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_RV_TIMER)) == ADDR_SPACE_RV_TIMER) begin
- dev_sel_s1n_8 = 3'd3;
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_RV_TIMER)) == ADDR_SPACE_RV_TIMER) begin
+ dev_sel_s1n_9 = 4'd3;
- end else if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_USBDEV)) == ADDR_SPACE_USBDEV) begin
- dev_sel_s1n_8 = 3'd4;
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_USBDEV)) == ADDR_SPACE_USBDEV) begin
+ dev_sel_s1n_9 = 4'd4;
- end else if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_PWRMGR)) == ADDR_SPACE_PWRMGR) begin
- dev_sel_s1n_8 = 3'd5;
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_PWRMGR)) == ADDR_SPACE_PWRMGR) begin
+ dev_sel_s1n_9 = 4'd5;
- end else if ((tl_s1n_8_us_h2d.a_address & ~(ADDR_MASK_RSTMGR)) == ADDR_SPACE_RSTMGR) begin
- dev_sel_s1n_8 = 3'd6;
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_RSTMGR)) == ADDR_SPACE_RSTMGR) begin
+ dev_sel_s1n_9 = 4'd6;
+
+ end else if ((tl_s1n_9_us_h2d.a_address & ~(ADDR_MASK_CLKMGR)) == ADDR_SPACE_CLKMGR) begin
+ dev_sel_s1n_9 = 4'd7;
end
end
@@ -118,17 +127,17 @@
tlul_socket_1n #(
.HReqDepth (4'h0),
.HRspDepth (4'h0),
- .DReqDepth ({7{4'h0}}),
- .DRspDepth ({7{4'h0}}),
- .N (7)
- ) u_s1n_8 (
+ .DReqDepth ({8{4'h0}}),
+ .DRspDepth ({8{4'h0}}),
+ .N (8)
+ ) u_s1n_9 (
.clk_i (clk_peri_i),
.rst_ni (rst_peri_ni),
- .tl_h_i (tl_s1n_8_us_h2d),
- .tl_h_o (tl_s1n_8_us_d2h),
- .tl_d_o (tl_s1n_8_ds_h2d),
- .tl_d_i (tl_s1n_8_ds_d2h),
- .dev_select (dev_sel_s1n_8)
+ .tl_h_i (tl_s1n_9_us_h2d),
+ .tl_h_o (tl_s1n_9_us_d2h),
+ .tl_d_o (tl_s1n_9_ds_h2d),
+ .tl_d_i (tl_s1n_9_ds_d2h),
+ .dev_select (dev_sel_s1n_9)
);
endmodule
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 8f65038..44a9332 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -86,6 +86,8 @@
tl_d2h_t tl_pwrmgr_d_d2h;
tl_h2d_t tl_rstmgr_d_h2d;
tl_d2h_t tl_rstmgr_d_d2h;
+ tl_h2d_t tl_clkmgr_d_h2d;
+ tl_d2h_t tl_clkmgr_d_d2h;
tl_h2d_t tl_nmi_gen_d_h2d;
tl_d2h_t tl_nmi_gen_d_d2h;
tl_h2d_t tl_usbdev_d_h2d;
@@ -106,21 +108,6 @@
assign tl_main_h_h2d = tl_peri_d_h2d;
assign tl_peri_d_d2h = tl_main_h_d2h;
- //clock wires declaration
- logic clk_fixed_powerup;
- logic clk_main_powerup;
- logic clk_usb_48mhz_powerup;
- logic clk_main_aes;
- logic clk_main_hmac;
- logic clk_main_infra;
- logic clk_fixed_infra;
- logic clk_fixed_secure;
- logic clk_main_secure;
- logic clk_fixed_peri;
- logic clk_usb_48mhz_peri;
- logic clk_fixed_timers;
- logic clk_proc_main;
-
// Signals
logic [31:0] mio2periph;
logic [31:0] periph2mio;
@@ -151,6 +138,7 @@
// alert_handler
// pwrmgr
// rstmgr
+ // clkmgr
// nmi_gen
// usbdev
logic cio_usbdev_sense_p2d;
@@ -249,25 +237,12 @@
flash_ctrl_pkg::flash_rsp_t flash_ctrl_flash_rsp;
pwrmgr_pkg::pwr_rst_req_t pwrmgr_pwr_rst_req;
pwrmgr_pkg::pwr_rst_rsp_t pwrmgr_pwr_rst_rsp;
+ pwrmgr_pkg::pwr_clk_req_t pwrmgr_pwr_clk_req;
+ pwrmgr_pkg::pwr_clk_rsp_t pwrmgr_pwr_clk_rsp;
rstmgr_pkg::rstmgr_out_t rstmgr_resets;
rstmgr_pkg::rstmgr_cpu_t rstmgr_cpu;
pwrmgr_pkg::pwr_cpu_t pwrmgr_pwr_cpu;
-
- // Clock assignments
- // These assignments are temporary until the creation of the clock controller
- assign clk_fixed_powerup = clk_fixed_i;
- assign clk_main_powerup = clk_i;
- assign clk_usb_48mhz_powerup = clk_usb_48mhz_i;
- assign clk_main_aes = clk_i;
- assign clk_main_hmac = clk_i;
- assign clk_main_infra = clk_i;
- assign clk_fixed_infra = clk_fixed_i;
- assign clk_fixed_secure = clk_fixed_i;
- assign clk_main_secure = clk_i;
- assign clk_fixed_peri = clk_fixed_i;
- assign clk_usb_48mhz_peri = clk_usb_48mhz_i;
- assign clk_fixed_timers = clk_fixed_i;
- assign clk_proc_main = clk_i;
+ clkmgr_pkg::clkmgr_out_t clkmgr_clocks;
// Non-debug module reset == reset for everything except for the debug module
logic ndmreset_req;
@@ -293,7 +268,7 @@
.PipeLine (IbexPipeLine)
) u_rv_core_ibex (
// clock and reset
- .clk_i (clk_proc_main),
+ .clk_i (clkmgr_clocks.clk_proc_main),
.rst_ni (rstmgr_resets.rst_sys_n),
.test_en_i (1'b0),
// static pinning
@@ -324,7 +299,7 @@
.NrHarts (1),
.IdcodeValue (JTAG_IDCODE)
) u_dm_top (
- .clk_i (clk_proc_main),
+ .clk_i (clkmgr_clocks.clk_proc_main),
.rst_ni (rstmgr_resets.rst_lc_n),
.testmode_i (1'b0),
.ndmreset_o (ndmreset_req),
@@ -364,7 +339,7 @@
.Outstanding(2),
.ErrOnWrite(1)
) u_tl_adapter_rom (
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_sys_n),
.tl_i (tl_rom_d_h2d),
@@ -385,7 +360,7 @@
.Width(32),
.Depth(4096)
) u_rom_rom (
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_sys_n),
.cs_i (rom_req),
.addr_i (rom_addr),
@@ -407,7 +382,7 @@
.SramDw(32),
.Outstanding(2)
) u_tl_adapter_ram_main (
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_sys_n),
.tl_i (tl_ram_main_d_h2d),
.tl_o (tl_ram_main_d_d2h),
@@ -428,7 +403,7 @@
.Depth(16384),
.DataBitsPerMask(8)
) u_ram1p_ram_main (
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_sys_n),
.req_i (ram_main_req),
@@ -454,7 +429,7 @@
.ByteAccess(0),
.ErrOnWrite(1)
) u_tl_adapter_eflash (
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_lc_n),
.tl_i (tl_eflash_d_h2d),
@@ -472,7 +447,7 @@
);
flash_phy u_flash_eflash (
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_lc_n),
.host_req_i (flash_host_req),
.host_addr_i (flash_host_addr),
@@ -506,7 +481,7 @@
.intr_rx_timeout_o (intr_uart_rx_timeout),
.intr_rx_parity_err_o (intr_uart_rx_parity_err),
- .clk_i (clk_fixed_secure),
+ .clk_i (clkmgr_clocks.clk_fixed_secure),
.rst_ni (rstmgr_resets.rst_sys_fixed_n)
);
@@ -524,7 +499,7 @@
// Interrupt
.intr_gpio_o (intr_gpio_gpio),
- .clk_i (clk_fixed_peri),
+ .clk_i (clkmgr_clocks.clk_fixed_peri),
.rst_ni (rstmgr_resets.rst_sys_fixed_n)
);
@@ -550,7 +525,7 @@
.intr_txunderflow_o (intr_spi_device_txunderflow),
.scanmode_i (scanmode_i),
- .clk_i (clk_fixed_peri),
+ .clk_i (clkmgr_clocks.clk_fixed_peri),
.rst_ni (rstmgr_resets.rst_spi_device_n)
);
@@ -570,7 +545,7 @@
.flash_o(flash_ctrl_flash_req),
.flash_i(flash_ctrl_flash_rsp),
- .clk_i (clk_main_infra),
+ .clk_i (clkmgr_clocks.clk_main_infra),
.rst_ni (rstmgr_resets.rst_lc_n)
);
@@ -581,7 +556,7 @@
// Interrupt
.intr_timer_expired_0_0_o (intr_rv_timer_timer_expired_0_0),
- .clk_i (clk_fixed_timers),
+ .clk_i (clkmgr_clocks.clk_fixed_timers),
.rst_ni (rstmgr_resets.rst_sys_fixed_n)
);
@@ -589,7 +564,7 @@
.tl_i (tl_aes_d_h2d),
.tl_o (tl_aes_d_d2h),
- .clk_i (clk_main_aes),
+ .clk_i (clkmgr_clocks.clk_main_aes),
.rst_ni (rstmgr_resets.rst_sys_n)
);
@@ -606,7 +581,7 @@
.alert_tx_o ( alert_tx[0:0] ),
.alert_rx_i ( alert_rx[0:0] ),
- .clk_i (clk_main_hmac),
+ .clk_i (clkmgr_clocks.clk_main_hmac),
.rst_ni (rstmgr_resets.rst_sys_n)
);
@@ -619,7 +594,7 @@
.irq_id_o (irq_id),
.msip_o (msip),
- .clk_i (clk_main_secure),
+ .clk_i (clkmgr_clocks.clk_main_secure),
.rst_ni (rstmgr_resets.rst_sys_n)
);
@@ -649,8 +624,8 @@
.dio_oe_o,
.dio_in_i,
- .clk_i (clk_main_secure),
- .clk_aon_i (clk_fixed_secure),
+ .clk_i (clkmgr_clocks.clk_main_secure),
+ .clk_aon_i (clkmgr_clocks.clk_fixed_secure),
.rst_ni (rstmgr_resets.rst_sys_n),
.rst_aon_ni (rstmgr_resets.rst_sys_fixed_n)
);
@@ -675,7 +650,7 @@
.esc_rx_i ( esc_rx ),
.esc_tx_o ( esc_tx ),
- .clk_i (clk_main_secure),
+ .clk_i (clkmgr_clocks.clk_main_secure),
.rst_ni (rstmgr_resets.rst_sys_n)
);
@@ -691,7 +666,8 @@
.pwr_ast_i(pwrmgr_pkg::PWR_AST_RSP_DEFAULT),
.pwr_rst_o(pwrmgr_pwr_rst_req),
.pwr_rst_i(pwrmgr_pwr_rst_rsp),
- .pwr_clk_o(),
+ .pwr_clk_o(pwrmgr_pwr_clk_req),
+ .pwr_clk_i(pwrmgr_pwr_clk_rsp),
.pwr_otp_o(),
.pwr_otp_i(pwrmgr_pkg::PWR_OTP_RSP_DEFAULT),
.pwr_lc_o(),
@@ -700,8 +676,8 @@
.pwr_cpu_i(pwrmgr_pwr_cpu),
.pwr_peri_i(pwrmgr_pkg::PWR_PERI_DEFAULT),
- .clk_i (clk_fixed_powerup),
- .clk_slow_i (clk_fixed_powerup),
+ .clk_i (clk_fixed_i),
+ .clk_slow_i (clk_fixed_i),
.rst_ni (rstmgr_resets.rst_por_n),
.rst_slow_ni (rstmgr_resets.rst_por_n)
);
@@ -718,13 +694,34 @@
.cpu_i(rstmgr_cpu),
.peri_i(rstmgr_pkg::RSTMGR_PERI_DEFAULT),
- .clk_i (clk_fixed_powerup),
- .clk_main_i (clk_main_powerup),
- .clk_fixed_i (clk_fixed_powerup),
- .clk_usb_i (clk_usb_48mhz_powerup),
+ .clk_i (clk_fixed_i),
+ .clk_main_i (clk_i),
+ .clk_fixed_i (clk_fixed_i),
+ .clk_usb_i (clk_usb_48mhz_i),
.rst_ni (rst_ni)
);
+ clkmgr u_clkmgr (
+ .tl_i (tl_clkmgr_d_h2d),
+ .tl_o (tl_clkmgr_d_d2h),
+
+ // Inter-module signals
+ .clocks_o(clkmgr_clocks),
+ .pwr_i(pwrmgr_pwr_clk_req),
+ .pwr_o(pwrmgr_pwr_clk_rsp),
+ .dft_i(clkmgr_pkg::CLK_DFT_DEFAULT),
+ .status_i(clkmgr_pkg::CLK_HINT_STATUS_DEFAULT),
+
+ .clk_i (clk_fixed_i),
+ .clk_main_i (clk_i),
+ .clk_fixed_i (clk_fixed_i),
+ .clk_usb_48mhz_i (clk_usb_48mhz_i),
+ .rst_ni (rstmgr_resets.rst_por_n),
+ .rst_main_ni (rstmgr_resets.rst_por_n),
+ .rst_fixed_ni (rstmgr_resets.rst_por_n),
+ .rst_usb_48mhz_ni (rstmgr_resets.rst_por_n)
+ );
+
nmi_gen u_nmi_gen (
.tl_i (tl_nmi_gen_d_h2d),
.tl_o (tl_nmi_gen_d_d2h),
@@ -738,7 +735,7 @@
.esc_rx_o ( esc_rx ),
.esc_tx_i ( esc_tx ),
- .clk_i (clk_main_secure),
+ .clk_i (clkmgr_clocks.clk_main_secure),
.rst_ni (rstmgr_resets.rst_sys_n)
);
@@ -786,8 +783,8 @@
.intr_frame_o (intr_usbdev_frame),
.intr_connected_o (intr_usbdev_connected),
- .clk_i (clk_fixed_peri),
- .clk_usb_48mhz_i (clk_usb_48mhz_peri),
+ .clk_i (clkmgr_clocks.clk_fixed_peri),
+ .clk_usb_48mhz_i (clkmgr_clocks.clk_usb_48mhz_peri),
.rst_ni (rstmgr_resets.rst_sys_fixed_n),
.rst_usb_48mhz_ni (rstmgr_resets.rst_usb_n)
);
@@ -848,8 +845,8 @@
// TL-UL Crossbar
xbar_main u_xbar_main (
- .clk_main_i (clk_main_infra),
- .clk_fixed_i (clk_fixed_infra),
+ .clk_main_i (clkmgr_clocks.clk_main_infra),
+ .clk_fixed_i (clkmgr_clocks.clk_fixed_infra),
.rst_main_ni (rstmgr_resets.rst_sys_n),
.rst_fixed_ni (rstmgr_resets.rst_sys_fixed_n),
.tl_corei_i (tl_corei_h_h2d),
@@ -886,7 +883,7 @@
.scanmode_i
);
xbar_peri u_xbar_peri (
- .clk_peri_i (clk_fixed_infra),
+ .clk_peri_i (clkmgr_clocks.clk_fixed_infra),
.rst_peri_ni (rstmgr_resets.rst_sys_fixed_n),
.tl_main_i (tl_main_h_h2d),
.tl_main_o (tl_main_h_d2h),
@@ -904,6 +901,8 @@
.tl_pwrmgr_i (tl_pwrmgr_d_d2h),
.tl_rstmgr_o (tl_rstmgr_d_h2d),
.tl_rstmgr_i (tl_rstmgr_d_d2h),
+ .tl_clkmgr_o (tl_clkmgr_d_h2d),
+ .tl_clkmgr_i (tl_clkmgr_d_d2h),
.scanmode_i
);
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.h b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
index 240d176..3789f0e 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.h
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
@@ -183,6 +183,14 @@
#define TOP_EARLGREY_RSTMGR_BASE_ADDR 0x400B0000u
/**
+ * Base address for clkmgr peripheral in top earlgrey.
+ *
+ * This should be used with #mmio_region_from_addr to access the memory-mapped
+ * registers associated with the peripheral (usually via a DIF).
+ */
+#define TOP_EARLGREY_CLKMGR_BASE_ADDR 0x400C0000u
+
+/**
* Base address for nmi_gen peripheral in top earlgrey.
*
* This should be used with #mmio_region_from_addr to access the memory-mapped
diff --git a/hw/top_earlgrey/top_earlgrey.core b/hw/top_earlgrey/top_earlgrey.core
index cbe9e08..4ca068a 100644
--- a/hw/top_earlgrey/top_earlgrey.core
+++ b/hw/top_earlgrey/top_earlgrey.core
@@ -9,6 +9,7 @@
depend:
- lowrisc:ip:uart:0.1
- lowrisc:top_earlgrey:alert_handler_reg
+ - lowrisc:top_earlgrey:clkmgr
- lowrisc:ip:alert_handler_component
- lowrisc:ip:gpio
- lowrisc:ip:rv_core_ibex
diff --git a/util/topgen.py b/util/topgen.py
index b86ee90..04b0e8d 100755
--- a/util/topgen.py
+++ b/util/topgen.py
@@ -18,10 +18,7 @@
import tlgen
from reggen import gen_dv, gen_rtl, gen_fpv, validate
-from topgen import get_hjsonobj_xbars, merge_top, search_ips, validate_top
-
-# Filter from IP list but adding generated hjson
-filter_list = ['rv_plic', 'pinmux', 'alert_handler']
+from topgen import get_hjsonobj_xbars, merge_top, search_ips, validate_top, amend_clocks
# Common header for generated files
genhdr = '''// Copyright lowRISC contributors.
@@ -423,6 +420,78 @@
validate.validate(hjson_obj)
gen_rtl.gen_rtl(hjson_obj, str(rtl_path))
+def generate_clkmgr(top, cfg_path, out_path):
+
+ # Target paths
+ rtl_path = out_path / 'ip/clkmgr/rtl/autogen'
+ rtl_path.mkdir(parents=True, exist_ok=True)
+ data_path = out_path / 'ip/clkmgr/data/autogen'
+ data_path.mkdir(parents=True, exist_ok=True)
+
+ # Template paths
+ hjson_tpl = cfg_path / '../ip/clkmgr/data/clkmgr.hjson.tpl'
+ rtl_tpl = cfg_path / '../ip/clkmgr/data/clkmgr.sv.tpl'
+ pkg_tpl = cfg_path / '../ip/clkmgr/data/clkmgr_pkg.sv.tpl'
+
+ hjson_out = data_path / 'clkmgr.hjson'
+ rtl_out = rtl_path / 'clkmgr.sv'
+ pkg_out = rtl_path / 'clkmgr_pkg.sv'
+
+ tpls = [hjson_tpl, rtl_tpl, pkg_tpl]
+ outputs = [hjson_out, rtl_out, pkg_out]
+ names = ['clkmgr.hjson', 'clkmgr.sv', 'clkmgr_pkg.sv']
+
+ # clock classification
+ grps = top['clocks']['groups']
+
+ ft_clks = OrderedDict()
+ rg_clks = OrderedDict()
+ sw_clks = OrderedDict()
+ hint_clks = OrderedDict()
+
+ ft_clks = {clk:src for grp in grps for (clk,src) in grp['clocks'].items()
+ if grp['name'] == 'powerup'}
+
+ # root-gate clocks
+ rg_clks = {clk:src for grp in grps for (clk,src) in grp['clocks'].items()
+ if grp['name'] != 'powerup' and grp['sw_cg'] == 'no'}
+
+ # direct sw control clocks
+ sw_clks = {clk:src for grp in grps for (clk,src) in grp['clocks'].items()
+ if grp['sw_cg'] == 'yes'}
+
+ # sw hint clocks
+ hint_clks = {clk:src for grp in grps for (clk,src) in grp['clocks'].items()
+ if grp['sw_cg'] == 'hint'}
+
+
+ out = StringIO()
+ for idx, tpl in enumerate(tpls):
+ with tpl.open(mode='r', encoding='UTF-8') as fin:
+ tpl = Template(fin.read())
+ try:
+ out = tpl.render(cfg=top,
+ ft_clks=ft_clks,
+ rg_clks=rg_clks,
+ sw_clks=sw_clks,
+ hint_clks=hint_clks)
+ except: # noqa: E722
+ log.error(exceptions.text_error_template().render())
+
+ if out == "":
+ log.error("Cannot generate {}".format(names[idx]))
+ return
+
+ with outputs[idx].open(mode='w', encoding='UTF-8') as fout:
+ fout.write(genhdr + out)
+
+ # Generate reg files
+ with open(str(hjson_out), 'r') as out:
+ hjson_obj = hjson.load(out,
+ use_decimal=True,
+ object_pairs_hook=OrderedDict)
+ validate.validate(hjson_obj)
+ gen_rtl.gen_rtl(hjson_obj, str(rtl_path))
def generate_top_ral(top, ip_objs, out_path):
# construct top ral block
@@ -571,6 +640,7 @@
outdir = Path(args.outdir)
out_path = Path(outdir)
+ cfg_path = Path(args.topcfg).parents[1]
if not args.no_gen_hjson or args.hjson_only:
# load top configuration
@@ -582,28 +652,38 @@
except ValueError:
raise SystemExit(sys.exc_info()[1])
+ # Create filtered list
+ filter_list = [module['name'] for module in topcfg['module']
+ if 'generated' in module and module['generated'] == 'true']
+ log.info("Filtered list is {}".format(filter_list))
+
topname = topcfg["name"]
# Sweep the IP directory and gather the config files
ip_dir = Path(__file__).parents[1] / 'hw/ip'
ips = search_ips(ip_dir)
- # exclude rv_plic (to use top_${topname} one) and
+ # exclude filtered IPs (to use top_${topname} one) and
ips = [x for x in ips if not x.parents[1].name in filter_list]
+ # Hack alert
+ # Generate clkmgr.hjson here so that it can be included below
+ # Unlike other generated hjsons, clkmgr thankfully does not require
+ # ip.hjson information. All the information is embedded within
+ # the top hjson file
+ amend_clocks(topcfg)
+ generate_clkmgr(topcfg, cfg_path, out_path)
+
# It may require two passes to check if the module is needed.
# TODO: first run of topgen will fail due to the absent of rv_plic.
# It needs to run up to amend_interrupt in merge_top function
# then creates rv_plic.hjson then run xbar generation.
hjson_dir = Path(args.topcfg).parent
- rv_plic_hjson = hjson_dir.parent / 'ip/rv_plic/data/autogen/rv_plic.hjson'
- ips.append(rv_plic_hjson)
- pinmux_hjson = hjson_dir.parent / 'ip/pinmux/data/autogen/pinmux.hjson'
- ips.append(pinmux_hjson)
-
- alert_handler_hjson = hjson_dir.parent / 'ip/alert_handler/data/autogen/alert_handler.hjson'
- ips.append(alert_handler_hjson)
+ for ip in filter_list:
+ log.info("Appending {}".format(ip))
+ ip_hjson = hjson_dir.parent / "ip/{}/data/autogen/{}.hjson".format(ip,ip)
+ ips.append(ip_hjson)
# load Hjson and pass validate from reggen
try:
@@ -679,6 +759,7 @@
if args.alert_handler_only:
sys.exit()
+ # Generate Pinmux
generate_pinmux(completecfg, out_path)
# Generate xbars
diff --git a/util/topgen/__init__.py b/util/topgen/__init__.py
index ed22f14..8661abf 100644
--- a/util/topgen/__init__.py
+++ b/util/topgen/__init__.py
@@ -3,6 +3,6 @@
# SPDX-License-Identifier: Apache-2.0
# noqa: F401 These functions are used in topgen.py
-from .merge import merge_top # noqa: F401
+from .merge import merge_top, amend_clocks # noqa: F401
from .validate import validate_top # noqa: F401
from .lib import search_ips, get_hjsonobj_xbars # noqa: F401
diff --git a/util/topgen/merge.py b/util/topgen/merge.py
index c531a85..9c45c61 100644
--- a/util/topgen/merge.py
+++ b/util/topgen/merge.py
@@ -422,6 +422,7 @@
Amend the clock connections of each entry to reflect the actual gated clock
"""
clks_attr = top['clocks']
+ clk_paths = clks_attr['hier_paths']
groups_in_top = [x["name"].lower() for x in clks_attr['groups']]
# Default assignments
@@ -454,10 +455,22 @@
# unique property of each group
unique = clks_attr['groups'][cg_idx]['unique']
+ # src property of each group
+ src = clks_attr['groups'][cg_idx]['src']
+
for port, clk in ep['clock_srcs'].items():
ep_clks.append(clk)
- if unique == "yes":
+ hier_name = clk_paths[src]
+
+ if src == 'ext':
+ # clock comes from top ports
+ if clk == 'main':
+ clk_name = "clk_i"
+ else:
+ clk_name = "clk_{}_i".format(clk)
+
+ elif unique == "yes":
# new unqiue clock name
clk_name = "clk_{}_{}".format(clk, ep_name)
@@ -469,7 +482,7 @@
clks_attr['groups'][cg_idx]['clocks'][clk_name] = clk
# add clock connections
- clock_connections[port] = clk_name
+ clock_connections[port] = hier_name + clk_name
# Add to endpoint structure
ep['clock_connections'] = clock_connections
@@ -674,7 +687,7 @@
# Assign clocks into appropriate groups
# Note, amend_ip references clock information to establish async handling
# as part of alerts.
- amend_clocks(gencfg)
+ # amend_clocks(gencfg)
# Add path names to declared resets
amend_resets(gencfg)
diff --git a/util/topgen/validate.py b/util/topgen/validate.py
index f29fa76..e34e173 100644
--- a/util/topgen/validate.py
+++ b/util/topgen/validate.py
@@ -91,6 +91,7 @@
clock_groups_required = {
'name': ['s', 'name of clock group'],
+ 'src': ['s', 'yes, no. This clock group is directly from source'],
'sw_cg': ['s', 'yes, no, hint. Software clock gate attributes'],
}
clock_groups_optional = {
@@ -180,6 +181,12 @@
group['sw_cg']))
error += 1
+ # Check combination of src and sw are valid
+ if group['src'] =='yes' and group['sw_cg'] != 'no':
+ log.error("Invalid combination of src and sw_cg: {} and {}".format(
+ group['src'], group['sw_cg']))
+ error += 1
+
# Check combination of sw_cg and unique are valid
unique = group['unique'] if 'unique' in group else 'no'
if group['sw_cg'] == 'no' and unique != 'no':