From 829f19c567596d5c178641d91ec405fa55b107bf Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Thu, 18 Apr 2024 22:51:19 +0100 Subject: [PATCH] Use deposits for Verilog blocking assignments --- src/jit/jit-dump.c | 2 +- src/jit/jit-exits.c | 15 +++++++++++++ src/jit/jit-exits.h | 2 ++ src/jit/jit-irgen.c | 21 +++++++++++++++++++ src/jit/jit-priv.h | 1 + src/rt/model.c | 16 ++++++++++++++ src/vcode.c | 19 ++++++++++++++++- src/vcode.h | 3 +++ src/vlog/vlog-lower.c | 49 ++++++++++++++++++++++++------------------- 9 files changed, 105 insertions(+), 23 deletions(-) diff --git a/src/jit/jit-dump.c b/src/jit/jit-dump.c index f44fc828..9b6674d6 100644 --- a/src/jit/jit-dump.c +++ b/src/jit/jit-dump.c @@ -88,7 +88,7 @@ const char *jit_exit_name(jit_exit_t exit) "CLEAR_EVENT", "IMPLICIT_EVENT", "ENTER_STATE", "REFLECT_VALUE", "REFLECT_SUBTYPE", "FUNCTION_TRIGGER", "ADD_TRIGGER", "TRANSFER_SIGNAL", "PORT_CONVERSION", "CONVERT_IN", "CONVERT_OUT", "BIND_FOREIGN", - "OR_TRIGGER", "CMP_TRIGGER", "INSTANCE_NAME", + "OR_TRIGGER", "CMP_TRIGGER", "INSTANCE_NAME", "DEPOSIT_SIGNAL", }; assert(exit < ARRAY_LEN(names)); return names[exit]; diff --git a/src/jit/jit-exits.c b/src/jit/jit-exits.c index e6124a25..5bab00ac 100644 --- a/src/jit/jit-exits.c +++ b/src/jit/jit-exits.c @@ -744,6 +744,21 @@ void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args, } break; + case JIT_EXIT_DEPOSIT_SIGNAL: + { + sig_shared_t *shared = args[0].pointer; + int32_t offset = args[1].integer; + int32_t count = args[2].integer; + jit_scalar_t value = { .integer = args[3].integer }; + bool scalar = args[4].integer; + + if (scalar) + x_deposit_signal(shared, offset, count, &value.integer); + else + x_deposit_signal(shared, offset, count, value.pointer); + } + break; + case JIT_EXIT_PUSH_SCOPE: { if (!jit_has_runtime(thread->jit)) diff --git a/src/jit/jit-exits.h b/src/jit/jit-exits.h index 83d29df4..5c63d903 100644 --- a/src/jit/jit-exits.h +++ b/src/jit/jit-exits.h @@ -77,6 +77,8 @@ void x_disconnect(sig_shared_t *ss, uint32_t offset, int32_t count, int64_t after, int64_t reject); void x_force(sig_shared_t *ss, uint32_t offset, int32_t count, void *values); void x_release(sig_shared_t *ss, uint32_t offset, int32_t count); +void x_deposit_signal(sig_shared_t *ss, uint32_t offset, int32_t count, + void *values); void x_resolve_signal(sig_shared_t *ss, jit_handle_t handle, void *context, int64_t ileft, int32_t nlits, int32_t flags); void x_elab_order_fail(tree_t where); diff --git a/src/jit/jit-irgen.c b/src/jit/jit-irgen.c index bfe7c8dd..a09190eb 100644 --- a/src/jit/jit-irgen.c +++ b/src/jit/jit-irgen.c @@ -3114,6 +3114,24 @@ static void irgen_op_release(jit_irgen_t *g, int op) macro_exit(g, JIT_EXIT_RELEASE); } +static void irgen_op_deposit_signal(jit_irgen_t *g, int op) +{ + jit_value_t shared = irgen_get_arg(g, op, 0); + jit_value_t offset = jit_value_from_reg(jit_value_as_reg(shared) + 1); + jit_value_t count = irgen_get_arg(g, op, 1); + jit_value_t value = irgen_get_arg(g, op, 2); + + jit_value_t scalar = irgen_is_scalar(g, op, 2); + + j_send(g, 0, shared); + j_send(g, 1, offset); + j_send(g, 2, count); + j_send(g, 3, value); + j_send(g, 4, scalar); + + macro_exit(g, JIT_EXIT_DEPOSIT_SIGNAL); +} + static void irgen_op_sched_event(jit_irgen_t *g, int op) { jit_value_t shared = irgen_get_arg(g, op, 0); @@ -3818,6 +3836,9 @@ static void irgen_block(jit_irgen_t *g, vcode_block_t block) case VCODE_OP_RELEASE: irgen_op_release(g, i); break; + case VCODE_OP_DEPOSIT_SIGNAL: + irgen_op_deposit_signal(g, i); + break; case VCODE_OP_EVENT: irgen_op_event(g, i); break; diff --git a/src/jit/jit-priv.h b/src/jit/jit-priv.h index 737410c3..bafee182 100644 --- a/src/jit/jit-priv.h +++ b/src/jit/jit-priv.h @@ -168,6 +168,7 @@ typedef enum { JIT_EXIT_OR_TRIGGER, JIT_EXIT_CMP_TRIGGER, JIT_EXIT_INSTANCE_NAME, + JIT_EXIT_DEPOSIT_SIGNAL, } jit_exit_t; typedef uint16_t jit_reg_t; diff --git a/src/rt/model.c b/src/rt/model.c index b5c80771..8c25e384 100644 --- a/src/rt/model.c +++ b/src/rt/model.c @@ -4301,6 +4301,22 @@ void x_release(sig_shared_t *ss, uint32_t offset, int32_t count) release_signal(m, s, offset, count); } +void x_deposit_signal(sig_shared_t *ss, uint32_t offset, int32_t count, + void *values) +{ + rt_signal_t *s = container_of(ss, rt_signal_t, shared); + + TRACE("deposit signal %s+%d value=%s count=%d", istr(tree_ident(s->where)), + offset, fmt_values(values, count), count); + + rt_proc_t *proc = get_active_proc(); + rt_model_t *m = get_model(); + + check_postponed(0, proc); + + deposit_signal(m, s, values, offset, count); +} + void x_resolve_signal(sig_shared_t *ss, jit_handle_t handle, void *context, int64_t ileft, int32_t nlits, int32_t flags) { diff --git a/src/vcode.c b/src/vcode.c index 80efa776..ebd29d92 100644 --- a/src/vcode.c +++ b/src/vcode.c @@ -959,7 +959,7 @@ const char *vcode_op_string(vcode_op_t op) "trap exp", "implicit event", "enter state", "reflect value", "reflect subtype", "function trigger", "add trigger", "transfer signal", "port conversion", "convert in", "convert out", "bind foreign", - "or trigger", "cmp trigger", "instance name", + "or trigger", "cmp trigger", "instance name", "deposit signal", }; if ((unsigned)op >= ARRAY_LEN(strs)) return "???"; @@ -1731,6 +1731,7 @@ void vcode_dump_with_mark(int mark_op, vcode_dump_fn_t callback, void *arg) case VCODE_OP_FORCE: case VCODE_OP_RELEASE: + case VCODE_OP_DEPOSIT_SIGNAL: { printf("%s ", vcode_op_string(op->kind)); vcode_dump_reg(op->args.items[0]); @@ -6016,6 +6017,22 @@ vcode_reg_t emit_instance_name(vcode_reg_t kind) return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar))); } +void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count, + vcode_reg_t values) +{ + op_t *op = vcode_add_op(VCODE_OP_DEPOSIT_SIGNAL); + vcode_add_arg(op, signal); + vcode_add_arg(op, count); + vcode_add_arg(op, values); + + VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL, + "deposit signal target is not signal"); + VCODE_ASSERT(vcode_reg_kind(count) == VCODE_TYPE_OFFSET, + "deposit signal count is not offset type"); + VCODE_ASSERT(vcode_reg_kind(values) != VCODE_TYPE_SIGNAL, + "signal cannot be values argument for deposit signal"); +} + void vcode_walk_dependencies(vcode_unit_t vu, vcode_dep_fn_t fn, void *ctx) { vcode_state_t state; diff --git a/src/vcode.h b/src/vcode.h index 9e4f301c..c3e32dd1 100644 --- a/src/vcode.h +++ b/src/vcode.h @@ -167,6 +167,7 @@ typedef enum { VCODE_OP_OR_TRIGGER, VCODE_OP_CMP_TRIGGER, VCODE_OP_INSTANCE_NAME, + VCODE_OP_DEPOSIT_SIGNAL, } vcode_op_t; typedef enum { @@ -527,5 +528,7 @@ void emit_convert_in(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count); void emit_convert_out(vcode_reg_t conv, vcode_reg_t nets, vcode_reg_t count); void emit_bind_foreign(vcode_reg_t spec, vcode_reg_t length, vcode_reg_t locus); vcode_reg_t emit_instance_name(vcode_reg_t kind); +void emit_deposit_signal(vcode_reg_t signal, vcode_reg_t count, + vcode_reg_t values); #endif // _VCODE_H diff --git a/src/vlog/vlog-lower.c b/src/vlog/vlog-lower.c index 5f7bad33..7ce73208 100644 --- a/src/vlog/vlog-lower.c +++ b/src/vlog/vlog-lower.c @@ -621,7 +621,7 @@ static void vlog_lower_timing(lower_unit_t *lu, vlog_node_t v, bool is_static) } } -static void vlog_lower_nbassign(lower_unit_t *lu, vlog_node_t v) +static void vlog_lower_procedural_assign(lower_unit_t *lu, vlog_node_t v) { vlog_node_t target = vlog_target(v); @@ -655,26 +655,36 @@ static void vlog_lower_nbassign(lower_unit_t *lu, vlog_node_t v) else data_reg = emit_unwrap(resize_reg); - vcode_type_t vtime = vtype_time(); - vcode_reg_t reject_reg = emit_const(vtime, 0); - vcode_reg_t after_reg = emit_const(vtime, 0); - - emit_sched_waveform(nets_reg, count_reg, data_reg, reject_reg, after_reg); -} + switch (vlog_kind(v)) { + case V_NBASSIGN: + case V_ASSIGN: + { + vcode_type_t vtime = vtype_time(); + vcode_reg_t reject_reg = emit_const(vtime, 0); + vcode_reg_t after_reg = emit_const(vtime, 0); -static void vlog_lower_bassign(lower_unit_t *lu, vlog_node_t v) -{ - vlog_lower_nbassign(lu, v); + emit_sched_waveform(nets_reg, count_reg, data_reg, + reject_reg, after_reg); + } + break; + case V_BASSIGN: + { + emit_deposit_signal(nets_reg, count_reg, data_reg); - // Delay one delta cycle to see the update + // Delay one delta cycle to see the update - vcode_type_t vtime = vtype_time(); - vcode_reg_t delay_reg = emit_const(vtime, 0); + vcode_type_t vtime = vtype_time(); + vcode_reg_t delay_reg = emit_const(vtime, 0); - vcode_block_t resume_bb = emit_block(); - emit_wait(resume_bb, delay_reg); + vcode_block_t resume_bb = emit_block(); + emit_wait(resume_bb, delay_reg); - vcode_select_block(resume_bb); + vcode_select_block(resume_bb); + } + break; + default: + CANNOT_HANDLE(v); + } } static void vlog_lower_systask(lower_unit_t *lu, vlog_node_t v) @@ -771,10 +781,8 @@ static void vlog_lower_stmts(lower_unit_t *lu, vlog_node_t v) vlog_lower_timing(lu, s, false); break; case V_NBASSIGN: - vlog_lower_nbassign(lu, s); - break; case V_BASSIGN: - vlog_lower_bassign(lu, s); + vlog_lower_procedural_assign(lu, s); break; case V_SEQ_BLOCK: vlog_lower_stmts(lu, s); @@ -814,7 +822,6 @@ static void vlog_driver_cb(vlog_node_t v, void *context) switch (vlog_kind(v)) { case V_NBASSIGN: - case V_BASSIGN: case V_ASSIGN: vlog_lower_driver(lu, vlog_target(v)); break; @@ -909,7 +916,7 @@ static void vlog_lower_continuous_assign(unit_registry_t *ur, vcode_select_block(start_bb); - vlog_lower_nbassign(lu, stmt); + vlog_lower_procedural_assign(lu, stmt); emit_wait(start_bb, VCODE_INVALID_REG); -- 2.39.2