Conversation
Greptile SummaryThis PR delivers targeted fixes for CUS-360, addressing memory-safety bugs in the liberty-defined generated clock path and hardening two waveform-generation helpers in Key changes:
Issues found:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant TCL as Tcl (create_clock)
participant SDC as Sdc::makeClock
participant LGC as Sdc::createLibertyGeneratedClocks
participant GC as GeneratedClock (Liberty)
participant MK as Sdc::makeGeneratedClock
participant CLK as Clock (runtime object)
TCL->>SDC: create_clock -period P [pin]
SDC->>SDC: deletePinClocks / deleteClkPinMappings (frees old Clock → edges_ freed)
SDC->>LGC: createLibertyGeneratedClocks(clk)
LGC->>GC: edges(), edgeShifts()
note over LGC: Deep-copy edges & edge_shifts<br/>(fix: prevents use-after-free on next redefinition)
LGC->>MK: makeGeneratedClock(..., edgesCopy, edgeShiftsCopy)
MK->>CLK: initGeneratedClk(edges=edgesCopy, ...)
CLK->>CLK: generateEdgesClk(src_clk)<br/>has_shifts = edge_shifts_ && size>=3<br/>masterClkEdgeTr: null/size guard
Last reviewed commit: "Fixups for CUS-360" |
| const FloatSeq *src_wave = src_clk->waveform(); | ||
| size_t src_size = src_wave->size(); | ||
| float src_period = src_clk->period(); | ||
| bool has_shifts = edge_shifts_ && edge_shifts_->size() >= 3; |
There was a problem hiding this comment.
Silent suppression of partial
edge_shifts_ without warning
has_shifts is set to false whenever edge_shifts_ has fewer than 3 entries but is still non-null. This means a non-empty edge_shifts_ vector with 1 or 2 entries will be silently ignored — no warning is emitted and the caller gets no feedback that their edge-shift data was discarded.
The old code suffered the opposite extreme (undefined behaviour by accessing out-of-bounds indices), but the new approach should at least warn when this edge case is hit, to make debugging easier:
| bool has_shifts = edge_shifts_ && edge_shifts_->size() >= 3; | |
| bool has_shifts = edge_shifts_ && edge_shifts_->size() >= 3; | |
| if (edge_shifts_ && !has_shifts) | |
| Sta::sta()->report()->warn(245, "generated clock edge_shifts size is less than three; shifts ignored."); |
Rule Used: Always add comments to explain the purpose of comp... (source)
Learnt From
Silimate/preqorsor-vscode#33
| int edge0_1 = (*edges_)[0] - 1; | ||
| float rise = (*src_wave)[edge0_1 % src_size] | ||
| + (edge0_1 / src_size) * src_period; |
There was a problem hiding this comment.
Potential modulo-by-zero if source waveform is empty
src_size is of type size_t and is derived from src_wave->size(). If the source clock has an empty waveform (size == 0), the expression edge0_1 % src_size is a modulo-by-zero operation (undefined behaviour in C++). The same pattern is repeated for edge1_1 and edge2_1.
This is a pre-existing condition that was not introduced by this PR, but since the function is being refactored here it is a good opportunity to add a guard:
if (src_size == 0) {
Sta::sta()->report()->warn(245, "generated clock source waveform is empty.");
return;
}
No description provided.