SystemVerilog OOP Mastery · All levels
Missing Features vs C++/Java and Reliable Workarounds: Code Examples
Code Examples for Missing Features vs C++/Java and Reliable Workarounds.
Code examples
Generic algorithms and overloaded APIs
systemverilog
// C++: template function + overloads
template <typename T>
T clamp(T v, T lo, T hi) {
return (v < lo) ? lo : ((v > hi) ? hi : v);
}
class Writer {
public:
void write(int v);
void write(const std::string& s);
};
// Java: generics + overloads
class WriterJ {
void write(int v) {}
void write(String s) {}
}
// SystemVerilog: parameterized classes + explicit method names
class fifo #(type T = int);
T q[$];
function void push(T item); q.push_back(item); endfunction
function T pop(); return q.pop_front(); endfunction
endclass
function int clamp_int(int v, int lo, int hi);
return (v < lo) ? lo : ((v > hi) ? hi : v);
endfunction
class writer_sv;
function void write_int(int v); $display("int=%0d", v); endfunction
function void write_str(string s); $display("str=%0s", s); endfunction
endclassSV supports type-parameterized classes but not full template-function ecosystems or signature-based overloads in classes, so APIs become explicitly named and type-specific.
Friend access and const-correctness
systemverilog
// C++: friend + const methods
class Token {
int secret;
friend class TokenInspector;
public:
int size() const { return 1; }
};
class TokenInspector {
public:
int read(const Token& t) { return t.secret; }
};
// SystemVerilog: explicit debug/export API + read-only conventions
class token;
local int secret;
function int debug_secret(bit allow);
if (allow) return secret;
return '0;
endfunction
function int size();
return 1; // convention: query method does not mutate state
endfunction
endclassWithout friend or const qualifiers on methods, SV teams encode privileged access and immutability through naming conventions, local/protected fields, and explicit accessor policies.
Namespaces and exceptions
systemverilog
// C++ namespace + exceptions
namespace proto {
class Crc {
public:
static uint32_t next(uint32_t d) { return d ^ 0x04C11DB7u; }
};
}
int parse_cfg(const std::string& p) {
if (p.empty()) throw std::runtime_error("missing path");
return 0;
}
// Java package + try/catch
package proto;
class CrcJ {
static int next(int d) { return d ^ 0x04C11DB7; }
}
// SystemVerilog package + status return
package proto_pkg;
class crc;
static function bit [31:0] next(bit [31:0] d);
return d ^ 32'h04C11DB7;
endfunction
endclass
typedef enum int {CFG_OK=0, CFG_ERR_PATH=1} cfg_status_e;
function cfg_status_e parse_cfg(string p);
if (p == "") return CFG_ERR_PATH;
return CFG_OK;
endfunction
endpackage
import proto_pkg::*;
cfg_status_e st = parse_cfg(cfg_path);
if (st != CFG_OK) begin
$error("parse_cfg failed status=%0d", st);
endSV uses packages for logical grouping and explicit status/error channels instead of exception propagation and catch blocks.