Output clocks of synthesized modules should be allowed to have no GATE port
#314 opened on Feb 3, 2021
Description
In the testsuite example bsc.names/portRenaming/prefixTests/sub_interfaces/Clock.bsv, you can see that we support renaming of output CLK and GATE signals via interface attritbutes, and in bsc.names/portRenaming/moduleArgs/ you can see examples of input GATE properties via module attributes -- some of which probably apply to output gates, but there aren't examples testing that (which should be fixed!) -- and via module argument attributes. However, the generated Verilog always has a gate port, even if the gate is constant asserted:
// oscillator and gates for output clock CLK_p1_p2
assign CLK_p1_p2 = CLK ;
assign CLK_GATE_p1_p2 = 1'd1 ;
We should support synthesizing modules without the gate port, when it's shown to be always asserted. This should at least be available with module attributes, if not also with interface attributes. This should be an easy fix (at least in BSV), once we decide what the syntax should be, so I've tagged this as a "good first issue". The place where the gate signal is created is in iExpandField for itClock (in IExpand.hs):
-- if the output clock is defined as an input clock, that input clock
-- must either have a gate port or the missing port must be inhigh
addInhighClkGate c
fi <- makeOutputClk True i (BetterInfo.mi_prefix bi) c
The argument True to makeOutputClk is indicating that this clock should have a gate port. The preceding lines are needed because we've taken the decision to have a clock gate; they add the assertion that, if this clock gate is coming from an input clock without a gate port, the gate port must be "inhigh", meaning that the value is assumed to always be true (distinguishing it from a gate port that's missing because we just don't have access to it, and can't assume that it's always asserted). Just as this code (and the code inside makeOutputClk) is consulting the pragmas to determine the names of the osc and gate signals, it can be made to consult the pragmas to decide if the gate signal should exist.
For input clocks, BSC assumes they have no gate unless specified with pragmas (such as gate_input_clocks, gate_all_clocks, and default_clock_gate on modules, or gate_inhigh and gate_unused on module arguments). For output clocks, I would would suspect that "unused" is meaningless and that the only semantics we should support are "there is no port, assume always True" and "there is a port, it must be used". (The only other possibility is "outhigh" which would be "there is a port, but assume it's constant True". But I see no reason to support that.) These could be specified in two places: (1) As interface attributes, on the interface type declaration (the same way we currently allow renaming attributes there) and (2) on the module definition, where we could an attribute like output_clock_no_gate (followed by), which asserts no gate port and BSC checks that the value for the gate is constant True (and errors if not). It has also been suggested that BSC could, on seeing that an output gate is constant True, silently generate Verilog without a gate port. This at first seems like a convenience, but at second thought it is unappealing: Until now, the list of ports on a synthesized module has been totally predictable from just looking at the code (the ifc, its attributes, and the module attributes). For the port list not to be known until after elaboration (or later!) kind of disturbs me. Possibly we could add a flag for this feature (-remove-true-clock-gates), but I'd be leery of doing it by default.
I would be in favor of keeping the current behavior of generating gates by default and adding a new module-attached attribute for specifying output clocks to not have gates (such as output_clock_no_gate), leaving interface-attached attributes as a possible later feature.
This is bug 1419 in Bluespec Inc's pre-GitHub bug database.