Conversation
3d62602 to
dd6dd0c
Compare
andreaskurth
left a comment
There was a problem hiding this comment.
Thanks @etterli and @glaserf, this is a nicely structured extension! 👍
Minor changes requested; nothing fundamental.
I checked this two ways. All three in-tree tops regenerate identically with this branch, so there is no regression on the non-split path. Then I made aon_timer a synthetic split IP (partitioned clocking, one interrupt and one extra alert in the secondary partition, an intra_p2s req/rcv pair, and secondary- and both-scoped exposed parameters) and instantiated it in top_earlgrey with domain: Main / domain_secondary: Aon. That works impressively well end to end: the alert slices and LpgMap entries land in the right per-domain buses and LPGs (LPG 5 = io_div4_timers + lc_io_div4[Main] for the primary, LPG 14 = aon_timers + lc_aon[Aon] for the secondary), the intra-IP signal is routed out of earlgrey_pd_main into earlgrey_pd_aon over a top-level net, TL/RACL/scan stay primary-only, and the domain == domain_secondary variant collapses to a local wire as documented. The comments below all come out of that experiment.
| # its own clock group and power domain. It need not be clocked at all, | ||
| # in which case there is nothing to elaborate for it. | ||
| if lib.secondary_key('clock_srcs') in ep: | ||
| ep[lib.secondary_key('clock_group')] = ep.get( |
There was a problem hiding this comment.
Defaulting clock_group_secondary here happens before validate_top runs, which I think makes the matching check in check_power_domains unreachable: by the time validate.py:1354 asks whether clock_group_secondary exists, this line has already created it.
The consequence is that a split instance written as clock_group: "timers" rather than clock_group: {primary: ..., secondary: ...} does not get the intended error; it silently generates the secondary partition into the secure group. I reproduced this: .clk_aon_i(clkmgr_clocks.clk_aon_secure) instead of clk_aon_timers, exit code 0.
Would it be better to default this only for a non-split instance, and let validation reject a missing clock_group_secondary?
There was a problem hiding this comment.
Good point. I've now added a proper validation of the secondary clocking information that it is consistent. If secondary clock_srcs is defined, the secondary clock_group and domain keys must also exist.
There was a problem hiding this comment.
The upfront consistency check does the job: the config that previously generated clk_aon_secure silently is now rejected.
Small wording point on one of the messages: for a split instance that writes clock_group: "timers" (a plain string rather than a per-partition dict) the error is "defines a secondary domain but no primary information is specified for clock_group". That reads as if the primary entry were missing, when the real problem is that the key is not partitioned at all. Would something like "clock_group is not specified per partition" be clearer?
dd6dd0c to
5174cef
Compare
etterli
left a comment
There was a problem hiding this comment.
Thanks @andreaskurth for the detailed review. Good catches. I've now addressed the first comments. Some fixes required also one additional reggen commit. Will continue tomorrow.
I refrained from rebasing on the merged reggen commits so the diff is simpler to compare.
a9cadbd to
0d58118
Compare
etterli
left a comment
There was a problem hiding this comment.
I've now also addressed the remaining feedback. These points gave raise to some additional improvements/changes.
- Power domains are now validated before any of its information is used.
- This resulted in autogen changes. The domain attribute is now emitted earlier. Otherwise there are no functional changes to the autogen files.
- A split IP's secondary partition must always be clocked.
- Intra-IP connections support req_rsp.
- CIO signals are emitted per partition for split IPs instead of for all partitions.
- Fixed a trailing comma issue in module instantiation for a split IP's secondary partition
The first push updates the changes. The 2nd one is a rebase on the current master.
| # its own clock group and power domain. It need not be clocked at all, | ||
| # in which case there is nothing to elaborate for it. | ||
| if lib.secondary_key('clock_srcs') in ep: | ||
| ep[lib.secondary_key('clock_group')] = ep.get( |
There was a problem hiding this comment.
Good point. I've now added a proper validation of the secondary clocking information that it is consistent. If secondary clock_srcs is defined, the secondary clock_group and domain keys must also exist.
andreaskurth
left a comment
There was a problem hiding this comment.
Thanks @etterli! Every point from the last review is addressed, and you found and fixed two things I had missed (the CIO declarations and the clkmgr idle hints). Making the secondary partition always clocked is a good simplification.
Two small blockers, both CI lint failures on the current head, plus one doc slip and two nits. Everything else LGTM, so approving because CI will tell when lint passes.
| # its own clock group and power domain. It need not be clocked at all, | ||
| # in which case there is nothing to elaborate for it. | ||
| if lib.secondary_key('clock_srcs') in ep: | ||
| ep[lib.secondary_key('clock_group')] = ep.get( |
There was a problem hiding this comment.
The upfront consistency check does the job: the config that previously generated clk_aon_secure silently is now rejected.
Small wording point on one of the messages: for a split instance that writes clock_group: "timers" (a plain string rather than a per-partition dict) the error is "defines a secondary domain but no primary information is specified for clock_group". That reads as if the primary entry were missing, when the real problem is that the key is not partitioned at all. Would something like "clock_group is not specified per partition" be clearer?
0d58118 to
e8f1566
Compare
etterli
left a comment
There was a problem hiding this comment.
Thanks again for the review. I've now fixed it and I think this is ready to merge.
However, as the AST split already surfaced some required changes I leave this PR as draft for now. I will merge it once the AST split draft is more mature.
e8f1566 to
8a95547
Compare
90158b7 to
455920c
Compare
1693eb1 to
84246e8
Compare
|
The last pushes contains the new topgen changes implemented during the AST split integration work. I don't expect further changes. The main new changes are (last 4 commits):
|
|
@andreaskurth PTAL |
A wakeup or reset-request is wired to pwrmgr through an inter-module signal of the same name. For a split IP this reference is resolved per partition, so reggen now requires the wakeup or reset-request to be declared in the same partition as its inter-module signal. This rejects a mismatch early instead of letting it surface as an unresolved inter-module reference in topgen. Also require a split IP to always declare clockings for its secondary partition. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
… connections This was not possible with the planned topgen changes. But the new implementation will allow this. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
The inter-module array-width check compared req/rsp widths that may be Parameter objects rather than plain ints. This factors the width resolution into a helper and resolves the requester width as well, such that the req/rsp array comparison always operates on integers. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
A split IP can have intra-IP connections which directly connect the two partitions. However, in the config a split IP is a single instance. So any regular inter-module signal would have the same start and end point, which is not supported by the current topgen. This commit thus introduces an intra-IP signal handling which uniquifies inter-module signals per partition. It does so by adding a partition qualifier to each inter-module signal of a split IP. This allows the regular inter-module signal handling to connect the two partitions properly. It also enables the partitions to use the same signal name, otherwise these would have to be unique. Non-split IPs use no qualifier. Co-authored-by: Florian Glaser <glaserf@lowrisc.org> Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
Wakeup, reset-request and idle-hint connections to pwrmgr/clkmgr were currently generated as <module>.<signal> references. For a split IP, Inter-module names are only unique per partition. This would give an ambigious signal choice. This commit adds logic to qualify these references with the signal's partition. Non-split IPs stay unqualified. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
Extends the hjson validator to handle the additional keys for split IPs. This prepares topgen to handle split IPs. topgen will emit additional keys for partitioned / split IPs. This commits adds the required code to validate such a configuration. It checks the secondary keys as well as that the split is configured properly. Co-authored-by: Florian Glaser <glaserf@lowrisc.org> Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
A split IP has nested dictionaries for certain keys. This flattens such a configuration by emitting keys for the secondary partition. It also adapts all the elaboration logic such that it can handle multiple partitions. It also validates that any secondary partition has proper clocking information. Co-authored-by: Florian Glaser <glaserf@lowrisc.org> Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
topgen uses certain power domain names before the actual validation code is run. This can lead to unexpected crashes especially when handling split IPs. This commit moves the domain validation before any of the domain information is used. This is possible as it is completely top dependend and does not require knowledge about the actual IPs. A consequence of this is that the domain key is emitted earlier as before in the autogen hjson files. Otherwise there is no functional change. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
This commit finally adds the full support for split IPs. A split IP consists of two partitions which can be instantiated in different power domains. topgen then automatically resolves the inter-module connections as well as intra-IP connections. All registers (TL-UL) stay in the primary partition. So do RACL and scan/DFT ports. Co-authored-by: Florian Glaser <glaserf@lowrisc.org> Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
Adds some basic documentation how to integrate a split IP into a top. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
This extends the templates such that external clocks are properly wired down to the receiving power domains. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
This extends topgen such that clocks can be sourced inside a partition/domain. Previously, clocks would have to be provided from outside a top. This now allows a clock to be inside a partition which then can be distributed to all domains/partitons. It has also implications on DFT signals. These are originating inside the top instead of being provided externally. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
This adds a small template which connects memory configurations from a unified struct to signals connecting to the consumers. It can be used inside a power domain to generate the local memory configuration wiring required to connect to the AST partitions. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
Previously, the xbar drivers assumed that each IP drives it xbar logic with clk_i. This commit generalized this such that the IP's primary clock is used. This is required for the AST split. Signed-off-by: Pascal Etterli <pascal.etterli@lowrisc.org>
84246e8 to
1c8f737
Compare
andreaskurth
left a comment
There was a problem hiding this comment.
Thanks @etterli. The split-IP part stays in good shape. This review is for the four commits added after my previous review & approval.
Major: [topgen] Support clock sources inside the top crashes for what looks like its main use case; see the comment on merge.py. An alert-bearing module whose primary clock is sourced inside the top hits AttributeError: 'ModuleClockRef' object has no attribute 'split'. CI does not catch it because no in-tree top uses an internal clock source, so every new path here is dormant.
Couple of other comments below.
Two process points, both worth your judgement rather than mine:
- The four new commits are not split-IP work.
[topgen] Support clock sources inside the topin particular is a feature of its own, with a new top-hjson schema and its own failure mode. Splitting it into a separate PR would make it easier to review now and easier to bisect later; it would also let the split-IP work land on its own. - One nit from round 2 is still open: the "no primary information is specified for
clock_group" message in_pre_validate_split_ip.
| clock_group = None | ||
| else: | ||
| # Discover what clock group we are related to. | ||
| clock_group = clock_groups[clk.split(".")[-1]] |
There was a problem hiding this comment.
This dereferences the raw clock_connections value, which may still be a ModuleClockRef placeholder rather than a net-name string.
create_alert_lpgs runs at topgen.py:1890, but the placeholders are only replaced by resolve_module_clocks at topgen.py:1904. So for any alert-bearing module whose primary clock is sourced inside the top, _make_lpg_entry reaches this line with a ModuleClockRef and topgen dies:
File "util/topgen/merge.py", line 1122, in _make_lpg_entry
clock_group = clock_groups[clk.split(".")[-1]]
AttributeError: 'ModuleClockRef' object has no attribute 'split'
I reproduced this on top_earlgrey by giving io_div4 module: "rv_dm", signal: "ndmreset_req" and putting aon_timer into the ast group (src: "ext"). The unmanaged-clock loop just above is also comparing a string against the placeholder, which silently never matches.
Since alert senders sit on the block's primary clock, I think this hits any AST-domain IP with alerts that takes an internally sourced clock. Could resolve_module_clocks run before create_alert_lpgs, or could the LPG code resolve the reference itself? If neither is easy, would it be worth raising a clear error here when the value is still a ModuleClockRef, so it fails with an explanation rather than an AttributeError?
| <% | ||
| # cfg type kind -> (req struct type, rsp struct type) | ||
| mem_cfg_types = { | ||
| '1p': ('prim_ram_1p_pkg::ram_1p_cfg_req_t', 'prim_ram_1p_pkg::ram_1p_cfg_rsp_t'), |
There was a problem hiding this comment.
Nothing in the repo includes this template. So it is never rendered, and neither the Python nor the generated SystemVerilog gets any coverage from CI. Would it be better to land it together with the AST-split change that uses it?
Two things inside it while it is unused, in case they get missed later:
mem_cfg_typesis defined but never referenced, and the loop unpackskindandwidthwithout using either; onlyfieldandwireare used.mem_cfg_lhs_padcallsmax()overmem_cfg_consumers, which raisesValueErroron an empty list. A guard or adefault=would make an empty consumer list a no-op instead.
|
|
||
| # Capture the producing module and its inter-signal, in case this clock is generated by an | ||
| # IP instance inside the top. | ||
| self.module = raw.get('module', None) |
There was a problem hiding this comment.
These three keys (module, signal, partition on a clock source) are new top-hjson schema, but I could not find them documented anywhere; util/topgen/README.md gained a "Split IPs" section for that feature, and there is no equivalent for this one.
Could the README get a short section covering how a clock source is declared as internally sourced, the constraint that the referenced signal must be a uni/req/logic inter-signal (which check_module_sourced_clocks enforces), and the requirement that a same-power-domain producer be listed in inter_module.top (which _resolve_module_clock raises on)? Those last two are discoverable only by hitting the errors.
| module = lib.find_module_by_name(top["module"] + top["xbar"], inst_name) | ||
| power_domain = module.get("domain").lower() | ||
| ## Extract the port name of the clock driving the xbar of the module. This is not available for | ||
| ## xbar nodes.These nodes also never reach the DRIVE_CHIP_TL_{HOST,DEVICE}_IF branches below. |
There was a problem hiding this comment.
Missing space after the period: "for xbar nodes.These nodes also never reach ..."
This builds on #31219 and adds the required
topgenextensions.