Skip to content

Commit 7c4c868

Browse files
authored
Merge branch 'master' into synlig_to_yosys_slang
2 parents c1c2a5d + 29cc58d commit 7c4c868

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2269
-958
lines changed

doc/src/api/vtrutil/logging.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ vtr_error
1414
:project: vtr
1515
:sections: briefdescription detaileddescription innernamespace innerclass user-defined public-func
1616

17+
.. _vtr_assertion:
18+
1719
vtr_assertion
1820
-------------
1921
.. doxygenfile:: vtr_assert.h

doc/src/dev/coding_style.rst

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
2+
Coding Style
3+
=============
4+
5+
.. note::
6+
7+
Many of the rules and conventions described in this document are not yet followed consistently throughout the codebase.
8+
They represent the direction we want to move in.
9+
Contributors are encouraged to adopt these guidelines in new code and when modifying existing code,
10+
so that the project gradually becomes more consistent and maintainable over time.
11+
12+
Header Guard Convention
13+
~~~~~~~~~~~~~~~~~~~~~
14+
15+
- Always use ``#pragma once`` as the first line in every header file, even before any file-level comments or code.
16+
17+
It is recommended that ``#pragma once`` appears before the file comment.
18+
The reason is that file comments may be duplicated each time the header is included,
19+
which can slow down compilation in large codebases due to extra file I/O.
20+
21+
Example:
22+
23+
.. code-block:: cpp
24+
25+
#pragma once
26+
27+
/**
28+
* @file netlist_walker.h
29+
* @brief Utilities for traversing the netlist.
30+
*/
31+
// ...rest of header...
32+
33+
Naming Conventions
34+
~~~~~~~~~~~~~
35+
36+
Consistent naming makes code easier to read, search, and maintain.
37+
The following rules help enforce a uniform naming style throughout the codebase:
38+
39+
General Rules
40+
-------------
41+
42+
- Use descriptive and unambiguous names.
43+
- Avoid abbreviations unless they are widely understood (e.g., `id`, `ctx`, `cfg`).
44+
- Prefer clarity over brevity.
45+
46+
Specific Conventions
47+
--------------------
48+
49+
- **Class names** use `PascalCase`.
50+
51+
.. code-block:: cpp
52+
53+
class DecompNetlistRouter {
54+
};
55+
56+
- **Variable and function names** use `snake_case`.
57+
58+
.. code-block:: cpp
59+
60+
int net_count;
61+
void estimate_wirelength();
62+
63+
- **Private member variables and private methods** should end with an underscore `_`.
64+
65+
.. code-block:: cpp
66+
67+
class Example {
68+
private:
69+
int count_;
70+
void update_state_();
71+
};
72+
73+
- **Enums** should use `enum class` instead of traditional enums. Enum names should start with `e_`.
74+
75+
.. code-block:: cpp
76+
77+
enum class e_heap_type {
78+
INVALID_HEAP = 0,
79+
BINARY_HEAP,
80+
FOUR_ARY_HEAP,
81+
};
82+
83+
- **Trivial structs** that primarily store data without behavior should be prefixed with `t_`.
84+
85+
.. code-block:: cpp
86+
87+
struct t_dijkstra_data {
88+
vtr::vector<RRNodeId, bool> node_expanded;
89+
vtr::vector<RRNodeId, float> node_visited_costs;
90+
std::priority_queue<PQ_Entry> pq;
91+
};
92+
93+
- **Source and header file names** use `snake_case` and should be short but descriptive.
94+
95+
Example: `router_lookahead_map.cpp`, `netlist_walker.h`
96+
97+
98+
99+
Commenting Style
100+
~~~~~~~~~~~~~~~~
101+
102+
Comments help readers understand the purpose, structure, and reasoning behind the code.
103+
This section outlines when and how to use comments in a consistent and helpful way.
104+
105+
General Rules
106+
-------------
107+
108+
- In **header files (`.h`)**, use comments to document *what* each API, class, struct, or function does.
109+
If the purpose, design, or behavior is not obvious, also explain *why* it is structured that way.
110+
- In **implementation files (`.cpp`)**, use comments to clarify *how* the code works,
111+
especially for non-obvious algorithms, tricky logic, or important implementation details.
112+
Only add comments where the code itself is not self-explanatory.
113+
- Do not restate what the code is plainly doing in the comments.
114+
- Keep comments up to date. Outdated comments are worse than no comments.
115+
- Use Doxygen-style `/** ... */` or `///` for documenting APIs, classes, structs, members, and files.
116+
117+
Comment types and rules:
118+
119+
- Use `/* ... */` **only** for Doxygen documentation comments.
120+
Do **not** use block comments (`/* */`) to describe code logic or individual lines in function bodies.
121+
122+
- Use `//` for all regular comments within function bodies or implementation code.
123+
124+
Formatting rules for `//` comments:
125+
126+
- Always include a space between `//` and the comment text.
127+
- Use full sentences when appropriate.
128+
- For multi-line comments, prefix each line with `// `.
129+
130+
Incorrect usage:
131+
132+
.. code-block:: cpp
133+
134+
/* Check if visited */ // Block comments are not allowed here
135+
if (visited[node_id]) {
136+
return;
137+
}
138+
139+
//Missing space
140+
//inconsistent formatting
141+
142+
/* Non-Doxygen block comment */ // Not permitted
143+
144+
.. note::
145+
146+
This strict separation between `/* ... */` and `//` comments is designed to improve readability and reduce mistakes.
147+
Using `/* ... */` only for Doxygen documentation makes it clear at a glance which comments are meant for generated docs,
148+
and which are for developers reading the code. When Doxygen (or similar) comments are visually distinct from inline implementation comments,
149+
it's harder to accidentally generate incomplete or misleading API documentation.
150+
151+
152+
When to Comment
153+
---------------
154+
155+
**1. File-Level Comments**
156+
- Every source/header file should begin with a brief comment explaining the overall purpose of the file.
157+
158+
**2. Classes and Structs**
159+
- Add a comment describing what the class or struct is for.
160+
- Comment every member variable to explain its role.
161+
162+
Example:
163+
164+
.. code-block:: cpp
165+
166+
/**
167+
* @brief Manages TCP connections for a server.
168+
*/
169+
class ConnectionManager {
170+
public:
171+
/**
172+
* @brief Starts listening for incoming connections.
173+
*/
174+
void Start();
175+
176+
private:
177+
int port_; ///< Listening port.
178+
bool is_running_; ///< Whether the server is active.
179+
};
180+
181+
182+
**3. Functions**
183+
- All non-trivial functions must have a Doxygen comment in the header file or on the static declaration.
184+
- Explain what the function does, its parameters, and its return value.
185+
186+
Example:
187+
188+
.. code-block:: cpp
189+
190+
/**
191+
* @brief Estimates the wirelength of a net using bounding box.
192+
*
193+
* @param net_id ID of the net to analyze.
194+
* @return Estimated wirelength in units.
195+
*/
196+
float estimate_wirelength(ClusterNetId net_id);
197+
198+
- For **static functions**, the comment describing *what* the function does should appear at the function's declaration
199+
(usually at the top of the `.cpp` file), not at its definition. Do not repeat the *what* comment at the implementation.
200+
Only add comments to the definition if there are non-obvious details about *how* or *why* the code works as it does.
201+
202+
Example:
203+
204+
.. code-block:: cpp
205+
206+
// Calculates the bounding box wirelength for a net.
207+
static float estimate_wirelength(ClusterNetId net_id);
208+
209+
static float estimate_wirelength(ClusterNetId net_id) {
210+
// Use HPWL to estimate the wirelngth
211+
// The estimated WL is adjusted based the net fanout
212+
...
213+
}
214+
215+
216+
217+
218+
Avoid Unnecessary Complexity
219+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
220+
221+
- Prefer easier-to-read language features and idioms.
222+
- Avoid overusing advanced C++ features (e.g., template metaprogramming, operator overloading, SFINAE) unless they are essential.
223+
- Write for clarity first; optimize for performance or conciseness only if needed and after measuring.
224+
225+
.. code-block:: cpp
226+
227+
// Prefer this
228+
const std::vector<int>& get_ids() const;
229+
230+
// Avoid this unless you truly need it
231+
template<typename T>
232+
auto&& get_ids() const && noexcept;
233+
234+
235+
- **Write short functions.** Functions should do one thing. Short functions are easier to understand, test, and reuse, and their purpose can be clearly described in a concise comment or documentation block.
236+
- **Limit function length.** If a function is growing too long or is difficult to describe in a sentence or two, consider splitting it into smaller helper functions.
237+
- **Favor simplicity.** Avoid clever or unnecessarily complex constructs. Code should be easy to read and maintain by others, not just the original author.
238+
- **Avoid deep abstract class hierarchies.** Excessive layering of virtual base classes makes the code hard to navigate and understand. Many tools (e.g., IDEs, LSPs) struggle to follow virtual call chains, especially in large or templated codebases.
239+
- **Avoid mixing templates with virtual functions.** This combination is particularly difficult to reason about and navigate. If you need to write generic code, prefer using either virtual dispatch or templates, but not both in the same interface.
240+
- Before adding new functions, classes, or utilities, check the codebase and documentation to see if a similar utility already exists.
241+
- Reuse or extend existing routines instead of duplicating functionality. This reduces bugs and makes the codebase more maintainable.
242+
243+
244+
245+
Group Related Data
246+
~~~~~~~~~~~~~~~~~~
247+
248+
- Group related data members into `structs` or `classes` rather than passing multiple related parameters separately.
249+
- Each data member and member function should be commented to explain its role, even in simple data structures.
250+
251+
.. code-block:: cpp
252+
253+
/**
254+
* @brief Data about a routing node.
255+
*/
256+
struct t_node_info {
257+
int id; ///< Unique identifier.
258+
float cost; ///< Routing cost.
259+
bool expanded; ///< True if this node has been expanded.
260+
};
261+
262+
// Instead of:
263+
void process_node(int node_id, float cost, bool expanded);
264+
265+
// Prefer:
266+
void process_node(const t_node_info& info);
267+
268+
.. note::
269+
270+
Organizing related data and routines in structs or classes with clear comments makes code easier to extend and understand.
271+
It also helps avoid errors from mismatched or misused arguments.
272+
273+
274+
275+
Assertion and Safety Check
276+
~~~~~~~~~~~~~~~~
277+
278+
Assertions help catch bugs early by checking that assumptions hold at runtime.
279+
Consistent use of assertions improves code reliability and helps developers identify problems close to their source.
280+
281+
General Guidelines
282+
------------------
283+
284+
- Use assertions and data structure validators wherever possible.
285+
- Prefer using `VTR_ASSERT` for checks that are inexpensive and should be enforced even in release builds.
286+
- In CPU-critical or performance-sensitive code, use `VTR_ASSERT_SAFE` for potentially expensive checks.
287+
These checks are disabled in release builds but are useful during development and debugging.
288+
289+
.. code-block:: cpp
290+
291+
// Cheap check: always on
292+
VTR_ASSERT(ptr != nullptr);
293+
294+
// Expensive check: enabled only in debug/development builds
295+
VTR_ASSERT_SAFE(is_valid_graph(rr_graph));
296+
297+
- Use assertions to document the assumptions and constraints in your code.
298+
- Prefer placing assertions as close as possible to where they might have been violated.
299+
300+
.. note::
301+
302+
For more on assertion macros and their behavior, see :ref:`vtr_assertion` for more details.
303+
304+
305+
Logging and Error Reporting
306+
~~~~~~~~~~~~~
307+
Use the VTR logging and error handling utilities instead of raw `printf`, `std::cerr`, `exit()`, or `throw`.
308+
309+
- Use `VTR_LOG`, `VTR_LOG_WARN`, and `VTR_LOG_ERROR`
310+
311+
312+
.. code-block:: cpp
313+
314+
VTR_LOG("Incr Slack updates %zu in %g sec\n", incr_slack_updates, incr_slack_update_time_sec);
315+
316+
if (check_route_option == e_check_route_option::OFF) {
317+
VTR_LOG_WARN("The user disabled the check route step.");
318+
return;
319+
}
320+
321+
if (total_edges_to_node[inode] != 0) {
322+
VTR_LOG_ERROR("in check_rr_graph: SOURCE node %d has a fanin of %d, expected 0.\n", inode, total_edges_to_node[inode]);
323+
}
324+
325+
326+
Refer to :doc:`Logging - Errors - Assertions</api/vtrutil/logging>` to learn more about logging and error reporting.
327+
328+
329+
330+
Use of `auto`
331+
~~~~~~~~~~~~~
332+
333+
Use `auto` only when the type is long, complex, or hard to write explicitly.
334+
335+
Examples where `auto` is appropriate:
336+
337+
.. code-block:: cpp
338+
339+
auto it = container.begin(); // Iterator type is long and not helpful to spell out
340+
341+
// The return type is std::vector<std::vector<std::pair<int, float>>>
342+
auto matrix = generate_adjacency_matrix();
343+
344+
// Lambdas have unreadable and compiler-generated types — use auto for them
345+
auto add = [](int x, int y) { return x + y; };
346+
347+
348+
Avoid `auto` when the type is simple and clear:
349+
350+
.. code-block:: cpp
351+
352+
// Use type names when they are short and readable.
353+
for (RRNodeId node_id : device_ctx.rr_graph.nodes()) {
354+
t_rr_node_route_inf& node_inf = route_ctx.rr_node_route_inf[rr_id];
355+
}
356+
357+
int count = 0;
358+
std::string name = "example";
359+
std::vector<int> numbers = {1, 2, 3};
360+
361+
Avoid:
362+
363+
.. code-block:: cpp
364+
365+
auto count = 0; // Simple and obvious type
366+
auto name = std::string("x"); // Hides a short, clear type
367+
368+
for (auto node_id : device_ctx.rr_graph.nodes()) {
369+
// node_id is RRNodeId. Write it out for clarity.
370+
auto& node_inf = route_ctx.rr_node_route_inf[rr_id];
371+
// node_inf is t_rr_node_route_inf. Use the explicit type since it's simple and meaningful.
372+
}
373+
374+
Rationale: clear, explicit types help with readability and understanding. Avoid hiding simple types behind `auto`.

doc/src/dev/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ Developer Guide
1111
c_api_doc
1212
code_documentation
1313
tutorials/index
14+
coding_style
1415
../SUPPORT
1516
../LICENSE

0 commit comments

Comments
 (0)