4.6 KiB
Style Guide for ROSE (and other FLORA projects)
Coding style matters a lot. Good coding styles makes the code look better to the eye, and can help mitigate some pitfalls and confusions.
Indentation
For all indentation, use spaces, not tabs.
The rationale behind this is to avoid different indent width settings in different editors. It's a great trade-off of making your source file a little bigger for portability to different editors.
C
Use 8 spaces. This is not only to adhere to the Linux kernel's coding style, but also to prevent your indentation levels from getting too big.
Verilog/SystemVerilog
Use 4 spaces. Unlike C, HDL is more on the combinational logic
side, so we can expect some more if-else
clauses embedded together.
IMPORTANT: If the indentation is blowing lines off the 80-char width, you should probably consider refactoring the logic.
Python
Use 4 spaces. This is enough for scripts, and a choice by the people behind python.
Shell Scripts
Use 4 spaces. There might be arguments to make it 2, but 4 is the minimum if you want to spot something appearing in an incorrect level when you've been staring at the screen for 15 hours.
Line width
80 characters is preferred, but it can be extended by 20 characters or so to accommodate longer identifiers.
If it breaches 80 characters, consider breaking it into multiple lines.
However, it is important to note that when passing many parameters/logic, it should always be broken into logical chunks for each line.
Avoid magic numbers
Unless it's the bit-length of a byte or something that's commonly known and obvious at first glance, use a constant to store it.
Arrays
Avoid using arrays that are more than 2 dimensions. If you need to
store multiple dimensions of data, consider using struct
to clarify
what each dimension stores.
Naming schemes
Names are only meaningful to humans, and the rationale behind the following guidelines is to allow anyone reading the code to know what an identifier refers to without scrolling back to its definition or other references.
Snake case or camel case?
Snake case.
Scoping
For all identifiers, it's important to note the scope of their usage. Names are there to avoid confusion, not add to them, and the considerations about confusion should fall in the same scope as their usage.
Abbreviating
Using abbreviations is okay and a good idea under the right circumstances.
As a general rule of thumb, the aggressiveness of abbreviating words is inversely proportional to the size of the scope. But it's a bad idea to abbreviate global identifiers that are not commonly used.
Constants
For all constants, use ALL_CAPS.
Global identifiers
Use FULL NAMES unless it's something pre-agreed on or by
specifications like mosi
or sys_clk
.
Commenting
Comments are great, but don't over-comment, they are there for exactly two things:
- Tell people what the code does
- Give a signal for future development (e.g. implementation notes, usage warnings, required guarantees)
If you need to explain how your code does something using comments, it's a better idea to re-write the code.
Signals
Comment signals should always be contained in the same line so that
you can grep
for them, the only exception to this is within
documentation, where you usually search for them.
TODO
: something to be done in the futureNOTE
: keep note of something when using/running the codeIMPORTANT
: knowing this is crucial to using/running the codeREQUIRES
: requirements for the code to run properlyGUARANTEES
: guarantees that the code has this feature when ran
Output Messages
Like comment signals, messages should also be in complete lines and
grep
-friendly.
All messages should use capitalized signals denoting what type of
message it is (e.g. ERROR
, WARNING
, INFO
) and enclosed in square
brackets ('[' and ']') so they can be easily processed by sed
or
awk
.
If there is the need for a timestamp, put the timestamp after the signal but within the closing bracket, leave no spaces between the signal and the timestamp, and separate the two parts with a colon ':'.
Tricks and workarounds
Don't try to write "smart" code, instead, write code that everyone can understand without too much explanation.
Styles specific to Verilog/SystemVerilog
Always use logic
Unless absolutely necessary, use logic
or types built on top of
logic
. This is to incorporate the idea of ownership into the code.
Every bit of data should have only one unique driver.
Avoid inferring latches
Every bit of data should be verbosely passed to other blocks of code.