mirror of
https://github.com/verilator/verilator.git
synced 2024-12-28 18:27:34 +00:00
205 lines
5.2 KiB
Systemverilog
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
|