SV: add unconstrained class.randomize() / rand slice
Implement obj.randomize() that assigns RNG values to rand/randc integral properties and returns 1, so Accellera UVM can start using unconstrained randomization before a constraint solver lands.
This commit is contained in:
parent
16ce21072a
commit
fee8a0d67a
|
|
@ -9,7 +9,7 @@ Each item should be a dedicated `feat/<name>` branch, with tests/examples and a
|
||||||
3. **Virtual interfaces** + eventing on `vif.clk` — **partial** (see [virtual-interface.md](virtual-interface.md))
|
3. **Virtual interfaces** + eventing on `vif.clk` — **partial** (see [virtual-interface.md](virtual-interface.md))
|
||||||
4. **Clocking blocks** — enough for `@(vif.cb)` — **partial** (interface-local `@(bif.cb)`; see [clocking.md](clocking.md))
|
4. **Clocking blocks** — enough for `@(vif.cb)` — **partial** (interface-local `@(bif.cb)`; see [clocking.md](clocking.md))
|
||||||
5. **`mailbox` / `semaphore` builtins** (or solid class equivalents with blocking put/get) — **partial** (int mailbox + semaphore; see [mailbox-semaphore.md](mailbox-semaphore.md))
|
5. **`mailbox` / `semaphore` builtins** (or solid class equivalents with blocking put/get) — **partial** (int mailbox + semaphore; see [mailbox-semaphore.md](mailbox-semaphore.md))
|
||||||
6. **Constraints + `randomize()` / `randomize() with`** — start unconstrained `rand`, then solver
|
6. **Constraints + `randomize()` / `randomize() with`** — **partial** (unconstrained `rand`/`randc` only; see [randomize.md](randomize.md)); solver / `with` still missing
|
||||||
7. **`$cast` / `$typename` hardening** for factory patterns
|
7. **`$cast` / `$typename` hardening** for factory patterns
|
||||||
8. **Covergroups** — functional coverage
|
8. **Covergroups** — functional coverage
|
||||||
9. **DPI-C** — optional but common in real flows
|
9. **DPI-C** — optional but common in real flows
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Last updated: 2026-07-21
|
||||||
| Virtual interfaces | **Partial** on `feat/virtual-interface`: `virtual interface T` as class property / TF arg; assign interface instance; member R/W; `@(posedge vif.clk)`. See [`docs/virtual-interface.md`](virtual-interface.md) and [`examples/virtual_interface`](../examples/virtual_interface). |
|
| Virtual interfaces | **Partial** on `feat/virtual-interface`: `virtual interface T` as class property / TF arg; assign interface instance; member R/W; `@(posedge vif.clk)`. See [`docs/virtual-interface.md`](virtual-interface.md) and [`examples/virtual_interface`](../examples/virtual_interface). |
|
||||||
| Clocking blocks | **Partial** on `feat/clocking-blocks`: interface-local `clocking`; `@(bif.cb)`; `cb.sig` R/W with `#0` skew. See [`docs/clocking.md`](clocking.md) and [`examples/clocking`](../examples/clocking). |
|
| Clocking blocks | **Partial** on `feat/clocking-blocks`: interface-local `clocking`; `@(bif.cb)`; `cb.sig` R/W with `#0` skew. See [`docs/clocking.md`](clocking.md) and [`examples/clocking`](../examples/clocking). |
|
||||||
| Mailbox / semaphore | **Partial** on `feat/mailbox-semaphore`: compiler builtins; `mailbox #(int)` + blocking/nonblocking put/get/num; `semaphore` get/put/try_get. See [`docs/mailbox-semaphore.md`](mailbox-semaphore.md) and [`examples/mailbox_sem`](../examples/mailbox_sem). |
|
| Mailbox / semaphore | **Partial** on `feat/mailbox-semaphore`: compiler builtins; `mailbox #(int)` + blocking/nonblocking put/get/num; `semaphore` get/put/try_get. See [`docs/mailbox-semaphore.md`](mailbox-semaphore.md) and [`examples/mailbox_sem`](../examples/mailbox_sem). |
|
||||||
| Constraints / randomize | Missing |
|
| Constraints / randomize | **Partial** on `feat/randomize-unconstrained`: unconstrained `rand`/`randc` integral props via `obj.randomize()` (returns 1). No constraint solver / `with` yet. See [`docs/randomize.md`](randomize.md) and [`examples/randomize`](../examples/randomize). |
|
||||||
| Covergroups / DPI | Missing |
|
| Covergroups / DPI | Missing |
|
||||||
|
|
||||||
## Remotes
|
## Remotes
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Unconstrained `randomize()` / `rand` (Tier A #6, first slice)
|
||||||
|
|
||||||
|
Status: **partial** — unconstrained integral `rand`/`randc` only; no constraint solver.
|
||||||
|
|
||||||
|
## Supported in this slice
|
||||||
|
|
||||||
|
```systemverilog
|
||||||
|
class pkt;
|
||||||
|
rand bit [7:0] a;
|
||||||
|
rand bit [3:0] b;
|
||||||
|
bit [7:0] c; // non-rand left alone
|
||||||
|
function new(); c = 8'h11; endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
pkt p = new;
|
||||||
|
bit ok = p.randomize(); // returns 1; assigns random values to a,b
|
||||||
|
```
|
||||||
|
|
||||||
|
- `obj.randomize()` returns `1` on success (null / unknown class type → `0`)
|
||||||
|
- Assigns random 0/1 bits to all `rand` and `randc` **integral** (`bit`/`logic`/`reg` packed) instance properties
|
||||||
|
- Non-rand properties are unchanged
|
||||||
|
- `randc` is treated like `rand` for now (no cyclic guarantee)
|
||||||
|
|
||||||
|
## Encoding
|
||||||
|
|
||||||
|
| Layer | Role |
|
||||||
|
|-------|------|
|
||||||
|
| Parse | `rand`/`randc` already property qualifiers; `constraint` / `randomize() with` remain **sorry** |
|
||||||
|
| Elab | `obj.randomize()` → `$ivl_randomize(obj)` (expr or task) |
|
||||||
|
| Target API | `ivl_type_prop_rand()` exposes qualifiers to codegen |
|
||||||
|
| Codegen | `%urandom <wid>` + `%store/prop/v` per rand property |
|
||||||
|
| Runtime | `%urandom` fills vec4 with RNG bits (`std::mt19937`) |
|
||||||
|
|
||||||
|
## Deferred (do not claim)
|
||||||
|
|
||||||
|
- Constraint blocks / solver
|
||||||
|
- `randomize() with { ... }`
|
||||||
|
- `rand_mode` / `constraint_mode`
|
||||||
|
- True `randc` cyclic behavior
|
||||||
|
- Randomizing non-integral properties (reals, strings, class handles, arrays)
|
||||||
|
- `std::randomize` procedural form / inline constraints
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
[`examples/randomize/randomize_basic.sv`](../examples/randomize/randomize_basic.sv) — prints `PASSED`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./install/bin/iverilog -g2012 -o /tmp/rand.vvp examples/randomize/randomize_basic.sv
|
||||||
|
./install/bin/vvp /tmp/rand.vvp
|
||||||
|
```
|
||||||
|
|
||||||
|
See also [STATUS.md](STATUS.md) and [ROADMAP.md](ROADMAP.md).
|
||||||
23
elab_expr.cc
23
elab_expr.cc
|
|
@ -2036,6 +2036,14 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*,
|
||||||
signed_flag_ = false;
|
signed_flag_ = false;
|
||||||
return expr_width_;
|
return expr_width_;
|
||||||
}
|
}
|
||||||
|
/* Built-in unconstrained randomize() -> bit success. */
|
||||||
|
if (method_name == "randomize") {
|
||||||
|
expr_type_ = IVL_VT_BOOL;
|
||||||
|
expr_width_ = 1;
|
||||||
|
min_width_ = 1;
|
||||||
|
signed_flag_ = false;
|
||||||
|
return expr_width_;
|
||||||
|
}
|
||||||
NetScope*method = class_type->method_from_name(method_name);
|
NetScope*method = class_type->method_from_name(method_name);
|
||||||
|
|
||||||
if (method == 0) {
|
if (method == 0) {
|
||||||
|
|
@ -4198,6 +4206,21 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||||
return sys;
|
return sys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unconstrained std::randomize vertical slice: assign random
|
||||||
|
values to rand/randc integral properties; return 1. */
|
||||||
|
if (method_name == perm_string::literal("randomize")) {
|
||||||
|
if (!parms_.empty()) {
|
||||||
|
cerr << get_fileline() << ": sorry: randomize() with "
|
||||||
|
<< "arguments is not supported yet." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
NetESFunc*sys = new NetESFunc("$ivl_randomize",
|
||||||
|
&netvector_t::scalar_logic, 1);
|
||||||
|
sys->set_line(*this);
|
||||||
|
sys->parm(0, sub_expr);
|
||||||
|
return sys;
|
||||||
|
}
|
||||||
|
|
||||||
return elaborate_class_method_net_(des, scope, net, class_type,
|
return elaborate_class_method_net_(des, scope, net, class_type,
|
||||||
method_name, nullptr);
|
method_name, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
elaborate.cc
10
elaborate.cc
|
|
@ -4642,6 +4642,16 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||||
: sem_one_parm);
|
: sem_one_parm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (method_name == perm_string::literal("randomize")) {
|
||||||
|
static const std::vector<perm_string> no_parms;
|
||||||
|
if (!parms_.empty()) {
|
||||||
|
cerr << get_fileline() << ": sorry: randomize() with "
|
||||||
|
<< "arguments is not supported yet." << endl;
|
||||||
|
des->errors += 1;
|
||||||
|
}
|
||||||
|
return elaborate_sys_task_method_(des, scope, net, method_name,
|
||||||
|
"$ivl_randomize", no_parms);
|
||||||
|
}
|
||||||
NetScope*task = class_type->method_from_name(method_name);
|
NetScope*task = class_type->method_from_name(method_name);
|
||||||
if (task == 0) {
|
if (task == 0) {
|
||||||
// If an implicit this was added it is not an error if we
|
// If an implicit this was added it is not an error if we
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Unconstrained class.randomize() / rand vertical slice smoke test.
|
||||||
|
class pkt;
|
||||||
|
rand bit [7:0] a;
|
||||||
|
rand bit [3:0] b;
|
||||||
|
bit [7:0] c;
|
||||||
|
function new();
|
||||||
|
c = 8'h11;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module top;
|
||||||
|
pkt p;
|
||||||
|
bit ok;
|
||||||
|
initial begin
|
||||||
|
p = new;
|
||||||
|
ok = p.randomize();
|
||||||
|
if (!ok) $fatal(1, "randomize failed");
|
||||||
|
// a,b should be randomized (not X); c unchanged
|
||||||
|
if (p.a === 8'hxx) $fatal(1, "rand a still X");
|
||||||
|
if (p.b === 4'hx) $fatal(1, "rand b still X");
|
||||||
|
if (p.c !== 8'h11) $fatal(1, "non-rand mutated");
|
||||||
|
$display("a=%0h b=%0h c=%0h", p.a, p.b, p.c);
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
#! /home/jawad/Desktop/iverilog-uvm/install/bin/vvp
|
||||||
|
:ivl_version "14.0 (devel)" "(4fc765f91-dirty)";
|
||||||
|
:ivl_delay_selection "TYPICAL";
|
||||||
|
:vpi_time_precision + 0;
|
||||||
|
:vpi_module "/home/jawad/Desktop/iverilog-uvm/install/lib/ivl/system.vpi";
|
||||||
|
:vpi_module "/home/jawad/Desktop/iverilog-uvm/install/lib/ivl/vhdl_sys.vpi";
|
||||||
|
:vpi_module "/home/jawad/Desktop/iverilog-uvm/install/lib/ivl/vhdl_textio.vpi";
|
||||||
|
:vpi_module "/home/jawad/Desktop/iverilog-uvm/install/lib/ivl/v2005_math.vpi";
|
||||||
|
:vpi_module "/home/jawad/Desktop/iverilog-uvm/install/lib/ivl/va_math.vpi";
|
||||||
|
:vpi_module "/home/jawad/Desktop/iverilog-uvm/install/lib/ivl/v2009.vpi";
|
||||||
|
S_0x557fac363450 .scope package, "$unit" "$unit" 2 1;
|
||||||
|
.timescale 0 0;
|
||||||
|
C0x557fac34e5f0 .class "pkt" [3]
|
||||||
|
0: "a", "b8"
|
||||||
|
1: "b", "b4"
|
||||||
|
2: "c", "b8"
|
||||||
|
;
|
||||||
|
S_0x557fac376b30 .scope class, "pkt" "pkt" 3 2, 3 2 0, S_0x557fac363450;
|
||||||
|
.timescale 0 0;
|
||||||
|
S_0x557fac376ce0 .scope autofunction.obj, "new" "new" 3 6, 3 6 0, S_0x557fac376b30;
|
||||||
|
.timescale 0 0;
|
||||||
|
v0x557fac376ec0_0 .var/cobj "@";
|
||||||
|
TD_$unit.pkt.new ;
|
||||||
|
%load/obj v0x557fac376ec0_0;
|
||||||
|
%pushi/vec4 17, 0, 8;
|
||||||
|
%store/prop/v 2, 8; Store in logic property c
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%end;
|
||||||
|
S_0x557fac3635e0 .scope module, "top" "top" 3 11;
|
||||||
|
.timescale 0 0;
|
||||||
|
v0x557fac376fa0_0 .var/2u "ok", 0 0;
|
||||||
|
v0x557fac377080_0 .var/cobj "p";
|
||||||
|
.scope S_0x557fac3635e0;
|
||||||
|
T_1 ;
|
||||||
|
%alloc S_0x557fac376ce0;
|
||||||
|
%new/cobj C0x557fac34e5f0;
|
||||||
|
%store/obj v0x557fac376ec0_0;
|
||||||
|
%callf/obj TD_$unit.pkt.new, S_0x557fac376ce0;
|
||||||
|
%load/obj v0x557fac376ec0_0;
|
||||||
|
%free S_0x557fac376ce0;
|
||||||
|
%store/obj v0x557fac377080_0;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%urandom 8; randomize prop a
|
||||||
|
%cast2;
|
||||||
|
%store/prop/v 0, 8;
|
||||||
|
%urandom 4; randomize prop b
|
||||||
|
%cast2;
|
||||||
|
%store/prop/v 1, 4;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%pushi/vec4 1, 0, 1;
|
||||||
|
%cast2;
|
||||||
|
%store/vec4 v0x557fac376fa0_0, 0, 1;
|
||||||
|
%load/vec4 v0x557fac376fa0_0;
|
||||||
|
%nor/r;
|
||||||
|
%flag_set/vec4 8;
|
||||||
|
%jmp/0xz T_1.0, 8;
|
||||||
|
%vpi_call/w 3 17 "$fatal", 32'sb00000000000000000000000000000001, "randomize failed" {0 0 0};
|
||||||
|
T_1.0 ;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%prop/v 0;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%cmpi/e 255, 255, 8;
|
||||||
|
%jmp/0xz T_1.2, 6;
|
||||||
|
%vpi_call/w 3 19 "$fatal", 32'sb00000000000000000000000000000001, "rand a still X" {0 0 0};
|
||||||
|
T_1.2 ;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%prop/v 1;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%cmpi/e 15, 15, 4;
|
||||||
|
%jmp/0xz T_1.4, 6;
|
||||||
|
%vpi_call/w 3 20 "$fatal", 32'sb00000000000000000000000000000001, "rand b still X" {0 0 0};
|
||||||
|
T_1.4 ;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%prop/v 2;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%cmpi/ne 17, 0, 8;
|
||||||
|
%jmp/0xz T_1.6, 6;
|
||||||
|
%vpi_call/w 3 21 "$fatal", 32'sb00000000000000000000000000000001, "non-rand mutated" {0 0 0};
|
||||||
|
T_1.6 ;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%prop/v 0;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%prop/v 1;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%load/obj v0x557fac377080_0;
|
||||||
|
%prop/v 2;
|
||||||
|
%pop/obj 1, 0;
|
||||||
|
%vpi_call/w 3 22 "$display", "a=%0h b=%0h c=%0h", S<2,vec4,u8>, S<1,vec4,u4>, S<0,vec4,u8> {3 0 0};
|
||||||
|
%vpi_call/w 3 23 "$display", "PASSED" {0 0 0};
|
||||||
|
%end;
|
||||||
|
.thread T_1;
|
||||||
|
# The file index is used to find the file name in the following table.
|
||||||
|
:file_names 4;
|
||||||
|
"N/A";
|
||||||
|
"<interactive>";
|
||||||
|
"-";
|
||||||
|
"randomize_basic.sv";
|
||||||
|
|
@ -2401,6 +2401,8 @@ extern const char* ivl_type_name(ivl_type_t net);
|
||||||
extern int ivl_type_properties(ivl_type_t net);
|
extern int ivl_type_properties(ivl_type_t net);
|
||||||
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
|
extern const char* ivl_type_prop_name(ivl_type_t net, int idx);
|
||||||
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
|
extern ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx);
|
||||||
|
/* Return 1 if property is rand, 2 if randc, 0 otherwise. */
|
||||||
|
extern int ivl_type_prop_rand(ivl_type_t net, int idx);
|
||||||
|
|
||||||
/* Maximum element count for a queue type (0 = unbounded). Only valid
|
/* Maximum element count for a queue type (0 = unbounded). Only valid
|
||||||
* when ivl_type_base(net) == IVL_VT_QUEUE. */
|
* when ivl_type_base(net) == IVL_VT_QUEUE. */
|
||||||
|
|
|
||||||
13
t-dll-api.cc
13
t-dll-api.cc
|
|
@ -3315,6 +3315,19 @@ extern "C" ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx)
|
||||||
return class_type->get_prop_type(idx);
|
return class_type->get_prop_type(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" int ivl_type_prop_rand(ivl_type_t net, int idx)
|
||||||
|
{
|
||||||
|
const netclass_t*class_type = dynamic_cast<const netclass_t*>(net);
|
||||||
|
assert(class_type);
|
||||||
|
|
||||||
|
property_qualifier_t qual = class_type->get_prop_qual(idx);
|
||||||
|
if (qual.test_randc())
|
||||||
|
return 2;
|
||||||
|
if (qual.test_rand())
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" unsigned ivl_type_queue_max(ivl_type_t net)
|
extern "C" unsigned ivl_type_queue_max(ivl_type_t net)
|
||||||
{
|
{
|
||||||
if (net == 0) return 0;
|
if (net == 0) return 0;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,62 @@ void resize_vec4_wid(ivl_expr_t expr, unsigned wid)
|
||||||
fprintf(vvp_out, " %%pad/u %u;\n", wid);
|
fprintf(vvp_out, " %%pad/u %u;\n", wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unconstrained randomize: for each rand/randc integral property of
|
||||||
|
* the class, push random bits and store into the property. Leaves a
|
||||||
|
* 1-bit success (1) on the vec4 stack when leave_result is set.
|
||||||
|
*/
|
||||||
|
void draw_ivl_randomize(ivl_expr_t obj, int leave_result)
|
||||||
|
{
|
||||||
|
ivl_type_t cls = ivl_expr_net_type(obj);
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (cls == 0 && ivl_expr_type(obj) == IVL_EX_SIGNAL) {
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(obj);
|
||||||
|
if (sig)
|
||||||
|
cls = ivl_signal_net_type(sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_eval_object(obj);
|
||||||
|
|
||||||
|
if (cls == 0 || ivl_type_base(cls) != IVL_VT_CLASS) {
|
||||||
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
if (leave_result)
|
||||||
|
fprintf(vvp_out, " %%pushi/vec4 0, 0, 1;\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx = 0 ; idx < ivl_type_properties(cls) ; idx += 1) {
|
||||||
|
ivl_type_t ptype;
|
||||||
|
ivl_variable_type_t pbase;
|
||||||
|
unsigned wid;
|
||||||
|
|
||||||
|
if (ivl_type_prop_rand(cls, idx) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ptype = ivl_type_prop_type(cls, idx);
|
||||||
|
if (ptype == 0)
|
||||||
|
continue;
|
||||||
|
pbase = ivl_type_base(ptype);
|
||||||
|
if (pbase != IVL_VT_BOOL && pbase != IVL_VT_LOGIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wid = ivl_type_packed_width(ptype);
|
||||||
|
if (wid == 0)
|
||||||
|
wid = 1;
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%urandom %u; randomize prop %s\n",
|
||||||
|
wid, ivl_type_prop_name(cls, idx));
|
||||||
|
if (pbase == IVL_VT_BOOL)
|
||||||
|
fprintf(vvp_out, " %%cast2;\n");
|
||||||
|
fprintf(vvp_out, " %%store/prop/v %d, %u;\n", idx, wid);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||||
|
if (leave_result)
|
||||||
|
fprintf(vvp_out, " %%pushi/vec4 1, 0, 1;\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test if the draw_immediate_vec4 instruction can be used.
|
* Test if the draw_immediate_vec4 instruction can be used.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1270,6 +1326,18 @@ static void draw_sfunc_vec4(ivl_expr_t expr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unconstrained class.randomize(): fill rand/randc integral props. */
|
||||||
|
if (strcmp(ivl_expr_name(expr), "$ivl_randomize") == 0) {
|
||||||
|
ivl_expr_t obj = (parm_count > 0) ? ivl_expr_parm(expr, 0) : 0;
|
||||||
|
if (obj)
|
||||||
|
draw_ivl_randomize(obj, 1);
|
||||||
|
else
|
||||||
|
fprintf(vvp_out, " %%pushi/vec4 0, 0, 1;\n");
|
||||||
|
if (ivl_expr_width(expr) > 1)
|
||||||
|
fprintf(vvp_out, " %%pad/u %u;\n", ivl_expr_width(expr));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
draw_vpi_func_call(expr);
|
draw_vpi_func_call(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,11 @@ extern uint64_t get_number_immediate64(ivl_expr_t ex);
|
||||||
* evaluation is the vec4 result in the top of the vec4 expression stack.
|
* evaluation is the vec4 result in the top of the vec4 expression stack.
|
||||||
*/
|
*/
|
||||||
extern void draw_eval_vec4(ivl_expr_t ex);
|
extern void draw_eval_vec4(ivl_expr_t ex);
|
||||||
|
|
||||||
|
/* Emit unconstrained class randomize for $ivl_randomize(obj).
|
||||||
|
* Leaves a 1-bit success flag on the vec4 stack when leave_result!=0;
|
||||||
|
* otherwise pops the result (task form). */
|
||||||
|
extern void draw_ivl_randomize(ivl_expr_t obj, int leave_result);
|
||||||
extern void resize_vec4_wid(ivl_expr_t expr, unsigned wid);
|
extern void resize_vec4_wid(ivl_expr_t expr, unsigned wid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -2048,6 +2048,13 @@ static int show_system_task_call(ivl_statement_t net)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(stmt_name, "$ivl_randomize") == 0) {
|
||||||
|
ivl_expr_t obj = ivl_stmt_parm(net, 0);
|
||||||
|
if (obj)
|
||||||
|
draw_ivl_randomize(obj, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(stmt_name, "$ivl_semaphore$get") == 0) {
|
if (strcmp(stmt_name, "$ivl_semaphore$get") == 0) {
|
||||||
ivl_expr_t sem = ivl_stmt_parm(net, 0);
|
ivl_expr_t sem = ivl_stmt_parm(net, 0);
|
||||||
if (sem) draw_eval_object(sem);
|
if (sem) draw_eval_object(sem);
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,7 @@ extern bool of_SEM_PUT(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SEM_TRY_GET(vthread_t thr, vvp_code_t code);
|
extern bool of_SEM_TRY_GET(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_BOX_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_BOX_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_UNBOX_VEC4(vthread_t thr, vvp_code_t code);
|
extern bool of_UNBOX_VEC4(vthread_t thr, vvp_code_t code);
|
||||||
|
extern bool of_URANDOM(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
|
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_NOR(vthread_t thr, vvp_code_t code);
|
extern bool of_NOR(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_NORR(vthread_t thr, vvp_code_t code);
|
extern bool of_NORR(vthread_t thr, vvp_code_t code);
|
||||||
|
|
|
||||||
|
|
@ -403,6 +403,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||||
{ "%test_nul/obj", of_TEST_NUL_OBJ, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
{ "%test_nul/obj", of_TEST_NUL_OBJ, 0,{OA_NONE, OA_NONE, OA_NONE} },
|
||||||
{ "%test_nul/prop",of_TEST_NUL_PROP,2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
{ "%test_nul/prop",of_TEST_NUL_PROP,2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
{ "%unbox/vec4",of_UNBOX_VEC4,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
{ "%unbox/vec4",of_UNBOX_VEC4,1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
|
{ "%urandom", of_URANDOM, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
|
||||||
{ "%vif/load/vec4", of_VIF_LOAD_VEC4, 2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
{ "%vif/load/vec4", of_VIF_LOAD_VEC4, 2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
{ "%vif/store/vec4",of_VIF_STORE_VEC4,2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
{ "%vif/store/vec4",of_VIF_STORE_VEC4,2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
{ "%vif/wait", of_VIF_WAIT, 2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
{ "%vif/wait", of_VIF_WAIT, 2,{OA_NUMBER, OA_BIT1, OA_NONE} },
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
# include <set>
|
# include <set>
|
||||||
# include <typeinfo>
|
# include <typeinfo>
|
||||||
# include <vector>
|
# include <vector>
|
||||||
|
# include <random>
|
||||||
# include <cstdlib>
|
# include <cstdlib>
|
||||||
# include <climits>
|
# include <climits>
|
||||||
# include <cstring>
|
# include <cstring>
|
||||||
|
|
@ -8632,3 +8633,30 @@ bool of_UNBOX_VEC4(vthread_t thr, vvp_code_t cp)
|
||||||
thr->push_vec4(res);
|
thr->push_vec4(res);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* %urandom <wid>
|
||||||
|
*
|
||||||
|
* Push <wid> bits of unconstrained random 0/1 onto the vec4 stack.
|
||||||
|
* Used by unconstrained class.randomize().
|
||||||
|
*/
|
||||||
|
bool of_URANDOM(vthread_t thr, vvp_code_t cp)
|
||||||
|
{
|
||||||
|
static std::mt19937 rng(std::random_device{}());
|
||||||
|
unsigned wid = cp->number;
|
||||||
|
vvp_vector4_t val(wid);
|
||||||
|
|
||||||
|
unsigned bit = 0;
|
||||||
|
while (bit < wid) {
|
||||||
|
uint32_t r = rng();
|
||||||
|
unsigned chunk = (wid - bit) < 32 ? (wid - bit) : 32;
|
||||||
|
for (unsigned i = 0 ; i < chunk ; i += 1) {
|
||||||
|
val.set_bit(bit + i, (r & 1u) ? BIT4_1 : BIT4_0);
|
||||||
|
r >>= 1;
|
||||||
|
}
|
||||||
|
bit += chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
thr->push_vec4(val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue