verilator/include/verilated_std.sv

205 lines
5.2 KiB
Systemverilog

// DESCRIPTION: Verilator: built-in packages and classes
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2022-2024 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU Lesser
// General Public License Version 3 or the Perl Artistic License Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
///
/// \file
/// \brief Verilated IEEE std:: header
///
/// This file is included automatically by Verilator, unless '--no-std-package'
/// is used.
///
/// This file is not part of the Verilated public-facing API.
/// It is only for internal use.
///
//*************************************************************************
//
// The following keywords from this file are hardcoded for detection in the parser:
// "mailbox", "process", "randomize", "semaphore", "std"
// verilator lint_off DECLFILENAME
// verilator lint_off TIMESCALEMOD
// verilator lint_off UNUSEDSIGNAL
package std;
class mailbox #(type T);
protected int m_bound;
protected T m_queue[$];
function new(int bound = 0);
m_bound = bound;
endfunction
function int num();
return m_queue.size();
endfunction
task put(T message);
`ifdef VERILATOR_TIMING
while (m_bound != 0 && m_queue.size() >= m_bound)
wait (m_queue.size() < m_bound);
m_queue.push_back(message);
`endif
endtask
function int try_put(T message);
if (m_bound == 0 || num() < m_bound) begin
m_queue.push_back(message);
return 1;
end
return 0;
endfunction
task get(ref T message);
`ifdef VERILATOR_TIMING
while (m_queue.size() == 0) begin
wait (m_queue.size() > 0);
end
message = m_queue.pop_front();
`endif
endtask
function int try_get(ref T message);
if (num() > 0) begin
message = m_queue.pop_front();
return 1;
end
return 0;
endfunction
task peek(ref T message);
`ifdef VERILATOR_TIMING
while (m_queue.size() == 0) begin
wait (m_queue.size() > 0);
end
message = m_queue[0];
`endif
endtask
function int try_peek(ref T message);
if (num() > 0) begin
message = m_queue[0];
return 1;
end
return 0;
endfunction
endclass
class semaphore;
protected int m_keyCount;
function new(int keyCount = 0);
m_keyCount = keyCount;
endfunction
function void put(int keyCount = 1);
m_keyCount += keyCount;
endfunction
task get(int keyCount = 1);
`ifdef VERILATOR_TIMING
while (m_keyCount < keyCount) begin
wait (m_keyCount >= keyCount);
end
m_keyCount -= keyCount;
`endif
endtask
function int try_get(int keyCount = 1);
if (m_keyCount >= keyCount) begin
m_keyCount -= keyCount;
return 1;
end
return 0;
endfunction
endclass
class process;
typedef enum {
FINISHED = 0,
RUNNING = 1,
WAITING = 2,
SUSPENDED = 3,
KILLED = 4
} state;
`ifdef VERILATOR_TIMING
// Width visitor changes it to VlProcessRef
protected chandle m_process;
`endif
static function process self();
process p = new;
`ifdef VERILATOR_TIMING
$c(p.m_process, " = vlProcess;");
`endif
return p;
endfunction
protected function void set_status(state s);
`ifdef VERILATOR_TIMING
$c(m_process, "->state(", s, ");");
`endif
endfunction
function state status();
`ifdef VERILATOR_TIMING
return state'($c(m_process, "->state()"));
`else
return RUNNING;
`endif
endfunction
function void kill();
set_status(KILLED);
endfunction
function void suspend();
$error("std::process::suspend() not supported");
endfunction
function void resume();
set_status(RUNNING);
endfunction
task await();
`ifdef VERILATOR_TIMING
wait (status() == FINISHED || status() == KILLED);
`endif
endtask
// When really implemented, srandom must operate on the process, but for
// now rely on the srandom() that is automatically generated for all
// classes.
//
// function void srandom(int seed);
// endfunction
// The methods below work only if set_randstate is never applied to
// a state string created before another such string. Full support
// could use VlRNG class to store the state per process in VlProcess
// objects.
function string get_randstate();
string s;
s.itoa($random); // Get a random number
set_randstate(s); // Pretend it's the state of RNG
return s;
endfunction
function void set_randstate(string s);
$urandom(s.atoi()); // Set the seed using a string
endfunction
endclass
function int randomize();
randomize = 0;
endfunction
endpackage