Skip to content

Commit

Permalink
[topgen] Support for unmanaged external resets
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 authored and andreaskurth committed Nov 26, 2024
1 parent 8568aec commit e97a8d9
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 24 deletions.
25 changes: 20 additions & 5 deletions hw/top_darjeeling/templates/toplevel.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import topgen.lib as lib
from reggen.params import Parameter
from topgen.clocks import Clocks
from topgen.resets import Resets
from topgen.merge import is_unmanaged_reset

num_mio_inputs = top['pinmux']['io_counts']['muxed']['inouts'] + \
top['pinmux']['io_counts']['muxed']['inputs']
Expand Down Expand Up @@ -129,6 +130,14 @@ module top_${top["name"]} #(
input prim_mubi_pkg::mubi4_t cg_${clk.name}_i,
% endfor
% endif
% if len(top['unmanaged_resets']._asdict().values()) > 0:

// Unmanaged external resets
% for rst in top['unmanaged_resets']._asdict().values():
input ${rst.signal_name},
input prim_mubi_pkg::mubi4_t ${rst.rst_en_signal_name},
% endfor
% endif

// All clocks forwarded to ast
output clkmgr_pkg::clkmgr_out_t clks_ast_o,
Expand Down Expand Up @@ -387,7 +396,7 @@ for rst in output_rsts:
cg_en = 'cg_' + lpg['clock_connection'].split('clk_')[-1]
else:
cg_en = top['clocks'].hier_paths['lpg'] + lpg['clock_connection'].split('.clk_')[-1]
rst_en = lib.get_reset_lpg_path(top, lpg['reset_connection'])
rst_en = lib.get_reset_lpg_path(top, lpg['reset_connection'], False, None, lpg['unmanaged_reset'])
known_clocks[cg_en] = 0
known_resets[rst_en] = 0
%>\
Expand Down Expand Up @@ -542,10 +551,16 @@ slice = str(alert_idx+w-1) + ":" + str(alert_idx)
.${k} (${v}),
% endfor
% for port, reset in m["reset_connections"].items():
% if lib.is_shadowed_port(block, port):
.${lib.shadow_name(port)} (${lib.get_reset_path(top, reset, True)}),
% endif:
.${port} (${lib.get_reset_path(top, reset)})${"," if not loop.last else ""}
<%
is_shadowed_port = lib.is_shadowed_port(block, port)
unmanaged_reset = is_unmanaged_reset(top, reset['name'])
reset_port = lib.get_reset_path(top, reset, False, unmanaged_reset)
shadowed_port = lib.get_reset_path(top, reset, True, unmanaged_reset)
%>\
% if is_shadowed_port:
.${lib.shadow_name(port)} (${shadowed_port}),
% endif
.${port} (${reset_port})${"," if not loop.last else ""}
% endfor
);
% endfor
Expand Down
25 changes: 25 additions & 0 deletions hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -16253,6 +16253,7 @@
lpg_idx: 17
}
]
unmanaged_resets: {}
exported_rsts: {}
alert_lpgs:
[
Expand All @@ -16275,6 +16276,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16300,6 +16302,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: spi_device
Expand All @@ -16325,6 +16328,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: i2c0
Expand All @@ -16350,6 +16354,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: i2c1
Expand All @@ -16375,6 +16380,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: i2c2
Expand All @@ -16397,6 +16403,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_timers
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16420,6 +16427,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_secure
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16445,6 +16453,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: spi_host0
Expand All @@ -16470,6 +16479,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div2_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: spi_host1
Expand All @@ -16495,6 +16505,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_usb_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: usb
Expand All @@ -16521,6 +16532,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_powerup
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: por_io_div4
Expand All @@ -16547,6 +16559,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_powerup
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16570,6 +16583,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_secure
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16595,6 +16609,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_peri
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16617,6 +16632,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_timers
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16642,6 +16658,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_infra
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16667,6 +16684,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_io_div4_infra
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc_io_div4
Expand All @@ -16692,6 +16710,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_infra
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc
Expand All @@ -16717,6 +16736,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_infra
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: sys
Expand All @@ -16740,6 +16760,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_secure
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc
Expand All @@ -16764,6 +16785,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_aes
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc
Expand All @@ -16788,6 +16810,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_hmac
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc
Expand All @@ -16812,6 +16835,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_kmac
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc
Expand All @@ -16836,6 +16860,7 @@
}
clock_connection: clkmgr_aon_clocks.clk_main_otbn
unmanaged_clock: false
unmanaged_reset: false
reset_connection:
{
name: lc
Expand Down
7 changes: 7 additions & 0 deletions hw/top_earlgrey/data/top_earlgrey.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@
],
},

// List of unmanaged external resets
//
// These should be listed as dictionaries that just give their names, in this form:
//
// { name: "my_external_reset" }
// unmanaged_resets: []

// This is the reset data structure of the design.
// The hier path refers to the reset reference path (struct / port)
// - The top/ext desgination follows the same scheme as inter-module
Expand Down
25 changes: 20 additions & 5 deletions hw/top_earlgrey/templates/toplevel.sv.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import topgen.lib as lib
from reggen.params import Parameter
from topgen.clocks import Clocks
from topgen.resets import Resets
from topgen.merge import is_unmanaged_reset

num_mio_inputs = top['pinmux']['io_counts']['muxed']['inouts'] + \
top['pinmux']['io_counts']['muxed']['inputs']
Expand Down Expand Up @@ -131,6 +132,14 @@ module top_${top["name"]} #(
input prim_mubi_pkg::mubi4_t cg_${clk.name}_i,
% endfor
% endif
% if len(top['unmanaged_resets']._asdict().values()) > 0:

// Unmanaged external resets
% for rst in top['unmanaged_resets']._asdict().values():
input ${rst.signal_name},
input prim_mubi_pkg::mubi4_t ${rst.rst_en_signal_name},
% endfor
% endif

input scan_rst_ni, // reset used for test mode
input scan_en_i,
Expand Down Expand Up @@ -406,7 +415,7 @@ for rst in output_rsts:
cg_en = 'cg_' + lpg['clock_connection'].split('clk_')[-1]
else:
cg_en = top['clocks'].hier_paths['lpg'] + lpg['clock_connection'].split('.clk_')[-1]
rst_en = lib.get_reset_lpg_path(top, lpg['reset_connection'])
rst_en = lib.get_reset_lpg_path(top, lpg['reset_connection'], False, None, lpg['unmanaged_reset'])
known_clocks[cg_en] = 0
known_resets[rst_en] = 0
%>\
Expand Down Expand Up @@ -561,10 +570,16 @@ slice = str(alert_idx+w-1) + ":" + str(alert_idx)
.${k} (${v}),
% endfor
% for port, reset in m["reset_connections"].items():
% if lib.is_shadowed_port(block, port):
.${lib.shadow_name(port)} (${lib.get_reset_path(top, reset, True)}),
% endif:
.${port} (${lib.get_reset_path(top, reset)})${"," if not loop.last else ""}
<%
is_shadowed_port = lib.is_shadowed_port(block, port)
unmanaged_reset = is_unmanaged_reset(top, reset['name'])
reset_port = lib.get_reset_path(top, reset, False, unmanaged_reset)
shadowed_port = lib.get_reset_path(top, reset, True, unmanaged_reset)
%>\
% if is_shadowed_port:
.${lib.shadow_name(port)} (${shadowed_port}),
% endif
.${port} (${reset_port})${"," if not loop.last else ""}
% endfor
);
% endfor
Expand Down
5 changes: 5 additions & 0 deletions hw/top_englishbreakfast/data/top_englishbreakfast.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
],
},

// List of unmanaged external resets
unmanaged_resets: [
// { name: "my_ext" }
]

// This is the reset data structure of the design.
// The hier path refers to the reset reference path (struct / port)
// - The top/ext desgination follows the same scheme as inter-module
Expand Down
22 changes: 15 additions & 7 deletions util/topgen/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from copy import deepcopy
from mako.template import Template
from pathlib import Path
from typing import Dict, List, Optional, Tuple
from typing import Dict, List, Optional, Tuple, Union

import hjson
from reggen.ip_block import IpBlock
Expand Down Expand Up @@ -586,19 +586,27 @@ def shadow_name(name: str) -> str:
return 'rst_shadowed_ni'


def get_reset_path(top: object, reset: str, shadow_sel: bool = False):
def get_reset_path(top: object, reset: Union[str, object], shadow_sel: bool = False,
unmanaged_reset: bool = False):
"""Return the appropriate reset path given name
"""
return top['resets'].get_path(reset['name'], reset['domain'], shadow_sel)
if unmanaged_reset:
return top['unmanaged_resets'].get(reset['name']).signal_name
else:
return top['resets'].get_path(reset['name'], reset['domain'], shadow_sel)


def get_reset_lpg_path(top: object, reset: str, shadow_sel: bool = False, domain: bool = None):
def get_reset_lpg_path(top: object, reset: Union[str, object], shadow_sel: bool = False,
domain: bool = None, unmanaged_reset: bool = False):
"""Return the appropriate LPG reset path given name
"""
if domain is not None:
return top['resets'].get_lpg_path(reset['name'], domain, shadow_sel)
if unmanaged_reset:
return top['unmanaged_resets'].get(reset['name']).rst_en_signal_name
else:
return top['resets'].get_lpg_path(reset['name'], reset['domain'], shadow_sel)
if domain is not None:
return top['resets'].get_lpg_path(reset['name'], domain, shadow_sel)
else:
return top['resets'].get_lpg_path(reset['name'], reset['domain'], shadow_sel)


def get_unused_resets(top):
Expand Down
Loading

0 comments on commit e97a8d9

Please sign in to comment.