Skip to content

Commit 8f1fcc9

Browse files
authored
Merge pull request #1065 from steveicarus/vvp-undriven-net-initialisation
vvp undriven net initialisation
2 parents 151a14d + fc9fcb0 commit 8f1fcc9

File tree

12 files changed

+249
-23
lines changed

12 files changed

+249
-23
lines changed

ivtest/vpi/br_gh1041.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <vpi_user.h>
2+
3+
static PLI_INT32 start_cb(struct t_cb_data *cb)
4+
{
5+
static struct t_vpi_value val;
6+
vpiHandle wire;
7+
8+
(void)cb; // suppress unused parameter warning
9+
10+
wire = vpi_handle_by_name("test.w4", NULL);
11+
if (wire) {
12+
val.format = vpiIntVal;
13+
val.value.integer = 1;
14+
vpi_put_value(wire, &val, NULL, vpiNoDelay);
15+
} else {
16+
vpi_printf("Failed to get handle for w4\n");
17+
}
18+
19+
wire = vpi_handle_by_name("test.w8", NULL);
20+
if (wire) {
21+
val.format = vpiIntVal;
22+
val.value.integer = 1;
23+
vpi_put_value(wire, &val, NULL, vpiNoDelay);
24+
} else {
25+
vpi_printf("Failed to get handle for w8\n");
26+
}
27+
28+
wire = vpi_handle_by_name("test.wr", NULL);
29+
if (wire) {
30+
val.format = vpiRealVal;
31+
val.value.real = 1.0;
32+
vpi_put_value(wire, &val, NULL, vpiNoDelay);
33+
} else {
34+
vpi_printf("Failed to get handle for wr\n");
35+
}
36+
37+
return 0;
38+
}
39+
40+
static void register_cb(void)
41+
{
42+
struct t_cb_data cbd = {};
43+
44+
cbd.reason = cbStartOfSimulation;
45+
cbd.cb_rtn = start_cb;
46+
vpi_register_cb(&cbd);
47+
}
48+
49+
void (*vlog_startup_routines[])(void) = {
50+
register_cb,
51+
0
52+
};

ivtest/vpi/br_gh1041.v

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module test;
2+
wire w4;
3+
tri0 w8;
4+
wire real wr;
5+
6+
reg failed = 0;
7+
8+
initial begin
9+
#0;
10+
$display("w4 %b w8 %b wr %f", w4, w8, wr);
11+
if (w4 !== 1'b1) failed = 1;
12+
if (w8 !== 1'b1) failed = 1;
13+
if (wr != 1.0) failed = 1;
14+
15+
if (failed)
16+
$display("FAILED");
17+
else
18+
$display("PASSED");
19+
end
20+
endmodule

ivtest/vpi/br_gh1041b.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <vpi_user.h>
2+
3+
static void step(void);
4+
5+
static vpiHandle w;
6+
7+
static PLI_INT32 tick_cb(struct t_cb_data *cb)
8+
{
9+
static struct t_vpi_value val = { .format = vpiIntVal };
10+
static int idx;
11+
12+
(void)cb;
13+
14+
++idx;
15+
val.value.integer = idx & 1;
16+
vpi_put_value(w, &val, NULL, vpiNoDelay);
17+
step();
18+
return 0;
19+
}
20+
21+
/* Request a callback after a delay. */
22+
23+
static void step(void)
24+
{
25+
static struct t_vpi_time now = { .type = vpiSimTime, .low = 2 };
26+
static struct t_cb_data cbd =
27+
{ .reason = cbAfterDelay, .cb_rtn = tick_cb, .time = &now };
28+
29+
/* Callback after delay. */
30+
31+
vpi_register_cb(&cbd);
32+
}
33+
34+
/* Callback function - simulation is starting. */
35+
36+
static PLI_INT32 start_cb(struct t_cb_data *cb)
37+
{
38+
static struct t_vpi_value val = { .format = vpiIntVal };
39+
40+
(void)cb;
41+
42+
w = vpi_handle_by_name("test.w", NULL);
43+
if (!w)
44+
vpi_printf("No handle!\n");
45+
vpi_printf("Got handle for %s\n", vpi_get_str(vpiFullName, w));
46+
val.value.integer = 0;
47+
vpi_put_value(w, &val, NULL, vpiNoDelay);
48+
step();
49+
return 0;
50+
}
51+
52+
/* VPI initialisation. */
53+
54+
static void start(void)
55+
{
56+
static struct t_vpi_time now = { .type = vpiSimTime };
57+
static struct t_cb_data cbd = { .reason = cbStartOfSimulation,
58+
.time = &now, .cb_rtn = start_cb };
59+
60+
/* At this point VPI objects do not exist,
61+
* so request a callback once they do.
62+
*/
63+
64+
vpi_register_cb(&cbd);
65+
}
66+
67+
/* This is a table of registration functions. This table is the external
68+
* symbol that the VVP simulator looks for when loading this .vpi module.
69+
*/
70+
71+
void (*vlog_startup_routines[])(void) = {
72+
start,
73+
0
74+
};

ivtest/vpi/br_gh1041b.v

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module test(w);
2+
input wire w;
3+
wire a, b;
4+
5+
6+
initial begin
7+
#11 $finish;
8+
end
9+
10+
assign b = 0;
11+
12+
assign a = !w | b;
13+
14+
always @(a) begin
15+
$display($time, ": Wire a is now ", a);
16+
end
17+
endmodule
18+

ivtest/vpi_gold/br_gh1041.gold

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Compiling vpi/br_gh1041.c...
2+
Making br_gh1041.vpi from br_gh1041.o...
3+
w4 1 w8 1 wr 1.000000
4+
PASSED

ivtest/vpi_gold/br_gh1041b.gold

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Compiling vpi/br_gh1041b.c...
2+
Making br_gh1041b.vpi from br_gh1041b.o...
3+
Got handle for test.w
4+
0: Wire a is now 1
5+
2: Wire a is now 0
6+
4: Wire a is now 1
7+
6: Wire a is now 0
8+
8: Wire a is now 1
9+
10: Wire a is now 0
10+
vpi/br_gh1041b.v:7: $finish called at 11 (1s)

ivtest/vpi_regress.list

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ br_gh308 normal br_gh308.c br_gh308.gold
7171
br_gh317 normal br_gh317.c br_gh317.gold
7272
br_gh496 normal,-g2009 br_gh496.c br_gh496.gold
7373
br_gh1037 normal,-g2009 br_gh1037.c br_gh1037.gold
74+
br_gh1041 normal br_gh1041.c br_gh1041.gold
75+
br_gh1041b normal br_gh1041b.c br_gh1041b.gold
7476
br_ml20191013 normal br_ml20191013.c br_ml20191013.gold
7577
by_index normal by_index.c by_index.gold
7678
by_name normal by_name.c by_name.log

tgt-vvp/draw_net_input.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001-2022 Stephen Williams ([email protected])
2+
* Copyright (c) 2001-2024 Stephen Williams ([email protected])
33
*
44
* This source code is free software; you can redistribute it
55
* and/or modify it in source code form under the terms of the GNU
@@ -651,18 +651,20 @@ static void draw_net_input_x(ivl_nexus_t nex,
651651
nex_data->flags |= nex_flags;
652652

653653
/* If the nexus has no drivers, then send a constant HiZ or
654-
0.0 into the net. */
654+
0.0 into the net. Use a lower case 'c' prefix for the
655+
constant to inform vvp that this is an undriven value. */
655656
if (ndrivers == 0) {
656657
unsigned wid = width_of_nexus(nex);
657658
int pull = (res == IVL_SIT_TRI0) || (res == IVL_SIT_TRI1);
658659
/* For real nets put 0.0. */
659660
if (signal_data_type_of_nexus(nex) == IVL_VT_REAL) {
660661
nex_private = draw_Cr_to_string(0.0);
662+
nex_private[0] = 'c';
661663
} else {
662664
unsigned jdx;
663665
char*tmp = malloc((pull ? 3 : 1) * wid + 5);
664666
nex_private = tmp;
665-
strcpy(tmp, pull ? "C8<" : "C4<");
667+
strcpy(tmp, pull ? "c8<" : "c4<");
666668
tmp += strlen(tmp);
667669
switch (res) {
668670
case IVL_SIT_TRI:

vvp/compile.cc

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2001-2021 Stephen Williams ([email protected])
2+
* Copyright (c) 2001-2024 Stephen Williams ([email protected])
33
*
44
* This source code is free software; you can redistribute it
55
* and/or modify it in source code form under the terms of the GNU
@@ -891,9 +891,20 @@ void compile_vpi_time_precision(long pre)
891891
*
892892
* The real value is sign * (mant ** exp).
893893
*/
894+
static bool crstring_header_test(const char*str)
895+
{
896+
if ((str[0] != 'C') && (str[0] != 'c'))
897+
return false;
898+
if ((str[1] != 'r') || (str[2] != '<'))
899+
return false;
900+
901+
return true;
902+
}
903+
894904
bool crstring_test(const char*str)
895905
{
896-
if (strncmp(str, "Cr<", 3) != 0) return false;
906+
if (!crstring_header_test(str))
907+
return false;
897908
const char*tp = strchr(str, '>');
898909
if (tp == 0) return false;
899910
if (tp[1] != 0) return false;
@@ -906,6 +917,8 @@ bool crstring_test(const char*str)
906917

907918
double crstring_to_double(const char*label)
908919
{
920+
assert(crstring_header_test(label));
921+
909922
const char*cp = label+3;
910923
assert(*cp == 'm');
911924
cp += 1;
@@ -956,14 +969,21 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
956969

957970
vvp_vector4_t tmp = c4string_to_vector4(label);
958971

959-
// Inputs that are constants are schedule to execute as
972+
// Inputs that are constants are scheduled to execute as
960973
// soon at the simulation starts. In Verilog, constants
961974
// start propagating when the simulation starts, just
962975
// like any other signal value. But letting the
963976
// scheduler distribute the constant value has the
964977
// additional advantage that the constant is not
965978
// propagated until the network is fully linked.
966-
schedule_set_vector(ifdx, tmp);
979+
// For constants that initialise an undriven net, we
980+
// schedule execution before time 0, to make sure it
981+
// occurs before any sensitive processes are started
982+
// or VPI callbacks are executed.
983+
if (label[0] == 'c')
984+
schedule_init_vector(ifdx, tmp);
985+
else
986+
schedule_set_vector(ifdx, tmp);
967987

968988
free(label);
969989
return;
@@ -973,7 +993,10 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
973993
if (c8string_test(label)) {
974994

975995
vvp_vector8_t tmp = c8string_to_vector8(label);
976-
schedule_set_vector(ifdx, tmp);
996+
if (label[0] == 'c')
997+
schedule_init_vector(ifdx, tmp);
998+
else
999+
schedule_set_vector(ifdx, tmp);
9771000

9781001
free(label);
9791002
return;
@@ -985,7 +1008,10 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label)
9851008

9861009
double tmp = crstring_to_double(label);
9871010

988-
schedule_set_vector(ifdx, tmp);
1011+
if (label[0] == 'c')
1012+
schedule_init_vector(ifdx, tmp);
1013+
else
1014+
schedule_set_vector(ifdx, tmp);
9891015
free(label);
9901016
return;
9911017
}

vvp/lexor.lex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
%{
66
/*
7-
* Copyright (c) 2001-2018 Stephen Williams ([email protected])
7+
* Copyright (c) 2001-2024 Stephen Williams ([email protected])
88
*
99
* This source code is free software; you can redistribute it
1010
* and/or modify it in source code form under the terms of the GNU
@@ -263,17 +263,17 @@ static char* strdupnew(char const *str)
263263

264264
/* Handle some specialized constant/literals as symbols. */
265265

266-
"C4<"[01xz]*">" {
266+
[Cc]"4<"[01xz]*">" {
267267
yylval.text = strdup(yytext);
268268
assert(yylval.text);
269269
return T_SYMBOL; }
270270

271-
"C8<"[01234567xz]*">" {
271+
[Cc]"8<"[01234567xz]*">" {
272272
yylval.text = strdup(yytext);
273273
assert(yylval.text);
274274
return T_SYMBOL; }
275275

276-
"Cr<m"[a-f0-9]*"g"[a-f0-9]*">" {
276+
[Cc]"r<m"[a-f0-9]*"g"[a-f0-9]*">" {
277277
yylval.text = strdup(yytext);
278278
assert(yylval.text);
279279
return T_SYMBOL; }

0 commit comments

Comments
 (0)