From 626644c4731cb153c9d2ba64a7aff667dbe19e34 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 11 Jul 2021 15:02:06 +0800 Subject: [PATCH] Rejig the layout of signals again --- src/cgen.c | 145 ++++++++++++++++++++++++++--------------- src/eval.c | 12 +++- src/lower.c | 35 +++++++--- src/rt/rtkern.c | 70 ++++++++++---------- src/vcode.c | 35 +++++++--- src/vcode.h | 3 +- test/group/signal3.vhd | 37 +++++++++++ test/test_elab.c | 2 - 8 files changed, 228 insertions(+), 111 deletions(-) create mode 100644 test/group/signal3.vhd diff --git a/src/cgen.c b/src/cgen.c index 63a7a5eb..3a6e3b01 100644 --- a/src/cgen.c +++ b/src/cgen.c @@ -213,12 +213,9 @@ static LLVMTypeRef llvm_uarray_type(LLVMTypeRef base, int dims) { const char *name = LLVMGetStructName(base); struct_name = xasprintf("uarray.%s.%d", name, dims); - is_signal = strncmp(name, "signal.", 7) == 0; + is_signal = strcmp(name, "signal") == 0; } break; - case LLVMPointerTypeKind: - struct_name = xasprintf("uarray.signal.%d", dims); - break; default: fatal_trace("cannot generate uarray type name for %s", LLVMPrintTypeToString(base)); @@ -247,35 +244,37 @@ static LLVMTypeRef llvm_uarray_type(LLVMTypeRef base, int dims) return new; } -static LLVMTypeRef llvm_signal_type(LLVMTypeRef base) +static LLVMTypeRef llvm_signal_shared_struct(void) { - char *struct_name LOCAL = NULL; - switch (LLVMGetTypeKind(base)) { - case LLVMIntegerTypeKind: - struct_name = xasprintf("signal.i%d", LLVMGetIntTypeWidth(base)); - break; - case LLVMDoubleTypeKind: - struct_name = xasprintf("signal.f"); - break; - case LLVMStructTypeKind: - struct_name = xasprintf("signal.%s", LLVMGetStructName(base)); - break; - default: - fatal_trace("cannot generate signal type name for %s", - LLVMPrintTypeToString(base)); - } + LLVMTypeRef exist = LLVMGetTypeByName(module, "sig_shared"); + if (exist != NULL) + return exist; - LLVMTypeRef exist = LLVMGetTypeByName(module, struct_name); + LLVMTypeRef fields[] = { + LLVMInt32Type(), // Signal ID + LLVMInt32Type(), // Pad + llvm_void_ptr() // Resolved pointer + }; + + LLVMTypeRef new = + LLVMStructCreateNamed(LLVMGetGlobalContext(), "sig_shared"); + LLVMStructSetBody(new, fields, ARRAY_LEN(fields), false); + return new; +} + +static LLVMTypeRef llvm_signal_type(void) +{ + LLVMTypeRef exist = LLVMGetTypeByName(module, "signal"); if (exist != NULL) return exist; LLVMTypeRef fields[] = { - LLVMInt32Type(), // Signal ID - LLVMInt32Type(), // Offset - LLVMPointerType(base, 0) // Resolved pointer + LLVMPointerType(llvm_signal_shared_struct(), 0), + LLVMInt32Type() // Offset }; - LLVMTypeRef new = LLVMStructCreateNamed(LLVMGetGlobalContext(), struct_name); + LLVMTypeRef new = + LLVMStructCreateNamed(LLVMGetGlobalContext(), "signal"); LLVMStructSetBody(new, fields, ARRAY_LEN(fields), false); return new; } @@ -403,16 +402,7 @@ static LLVMTypeRef cgen_type(vcode_type_t type) } case VCODE_TYPE_SIGNAL: - { - LLVMTypeRef base_type = NULL; - vcode_type_t vbase = vtype_base(type); - if (vtype_kind(vbase) == VCODE_TYPE_CARRAY) - base_type = cgen_type(vtype_elem(vbase)); - else - base_type = cgen_type(vbase); - - return llvm_signal_type(base_type); - } + return llvm_signal_type(); case VCODE_TYPE_FILE: return llvm_void_ptr(); @@ -875,6 +865,20 @@ static LLVMValueRef cgen_subprogram_arg(int op, int arg, cgen_ctx_t *ctx) return value; } +static LLVMValueRef cgen_make_signal_ptr(LLVMValueRef shared) +{ + LLVMTypeRef elems[2] = { + llvm_signal_type(), + LLVMInt32Type() // Pointer offset + }; + LLVMTypeRef sig_ptr_type = LLVMStructType(elems, 2, false); + + LLVMValueRef r = LLVMGetUndef(sig_ptr_type); + r = LLVMBuildInsertValue(builder, r, shared, 0, ""); + r = LLVMBuildInsertValue(builder, r, llvm_int32(0), 1, ""); + return r; +} + static void cgen_op_return(int op, cgen_ctx_t *ctx) { if (vcode_unit_kind() == VCODE_UNIT_PROCEDURE) { @@ -1132,15 +1136,27 @@ static void cgen_op_load(int op, cgen_ctx_t *ctx) { vcode_reg_t result = vcode_get_result(op); vcode_var_t var = vcode_get_address(op); - ctx->regs[result] = LLVMBuildLoad(builder, cgen_get_var(var, ctx), - cgen_reg_name(result)); + + LLVMValueRef loaded = LLVMBuildLoad(builder, cgen_get_var(var, ctx), + cgen_reg_name(result)); + + if (false && vcode_reg_kind(result) == VCODE_TYPE_SIGNAL) + ctx->regs[result] = cgen_make_signal_ptr(loaded); + else + ctx->regs[result] = loaded; } static void cgen_op_load_indirect(int op, cgen_ctx_t *ctx) { vcode_reg_t result = vcode_get_result(op); LLVMValueRef ptr = cgen_get_arg(op, 0, ctx); - ctx->regs[result] = LLVMBuildLoad(builder, ptr, cgen_reg_name(result)); + + LLVMValueRef loaded = LLVMBuildLoad(builder, ptr, cgen_reg_name(result)); + + if (false && vcode_reg_kind(result) == VCODE_TYPE_SIGNAL) + ctx->regs[result] = cgen_make_signal_ptr(loaded); + else + ctx->regs[result] = loaded; } static void cgen_op_add(int op, cgen_ctx_t *ctx) @@ -1731,8 +1747,13 @@ static void cgen_op_wrap(int op, cgen_ctx_t *ctx) static void cgen_op_unwrap(int op, cgen_ctx_t *ctx) { vcode_reg_t result = vcode_get_result(op); - ctx->regs[result] = LLVMBuildExtractValue(builder, cgen_get_arg(op, 0, ctx), + LLVMValueRef data = LLVMBuildExtractValue(builder, cgen_get_arg(op, 0, ctx), 0, cgen_reg_name(result)); + + if (false && vcode_reg_kind(result) == VCODE_TYPE_SIGNAL) + ctx->regs[result] = cgen_make_signal_ptr(data); + else + ctx->regs[result] = data; } static void cgen_op_index(int op, cgen_ctx_t *ctx) @@ -1894,8 +1915,17 @@ static void cgen_op_resolved(int op, cgen_ctx_t *ctx) { vcode_reg_t result = vcode_get_result(op); - LLVMValueRef sig_struct = cgen_get_arg(op, 0, ctx); - ctx->regs[result] = LLVMBuildExtractValue(builder, sig_struct, 2, ""); + // TODO: can offset be non-zero here? + + LLVMValueRef sigptr = cgen_get_arg(op, 0, ctx); + LLVMValueRef shared = LLVMBuildExtractValue(builder, sigptr, 0, ""); + + LLVMTypeRef result_type = cgen_type(vcode_reg_type(result)); + + LLVMValueRef resolved = LLVMBuildStructGEP(builder, shared, 2, "resolved"); + LLVMValueRef cast = LLVMBuildBitCast(builder, resolved, + LLVMPointerType(result_type, 0), ""); + ctx->regs[result] = LLVMBuildLoad(builder, cast, cgen_reg_name(result)); } static LLVMValueRef cgen_pointer_to_arg_data(int op, int arg, cgen_ctx_t *ctx) @@ -2144,7 +2174,7 @@ static void cgen_net_flag(int op, net_flags_t flag, cgen_ctx_t *ctx) LLVMValueRef count = cgen_get_arg(op, 1, ctx); LLVMValueRef args[] = { - LLVMBuildExtractValue(builder, sigptr, 0, "sid"), + LLVMBuildExtractValue(builder, sigptr, 0, "shared"), LLVMBuildExtractValue(builder, sigptr, 1, "offset"), count, llvm_int32(flag) @@ -2922,7 +2952,7 @@ static void cgen_op_init_signal(int op, cgen_ctx_t *ctx) LLVMValueRef sigptr = cgen_get_arg(op, 0, ctx); LLVMValueRef args[] = { - LLVMBuildExtractValue(builder, sigptr, 0, "sid"), + LLVMBuildExtractValue(builder, sigptr, 0, "shared"), LLVMBuildExtractValue(builder, sigptr, 1, "offset"), llvm_void_cast(cgen_pointer_to_arg_data(op, 1, ctx)) }; @@ -2931,13 +2961,20 @@ static void cgen_op_init_signal(int op, cgen_ctx_t *ctx) static void cgen_op_link_signal(int op, cgen_ctx_t *ctx) { - vcode_var_t var = vcode_get_address(op); + vcode_reg_t result = vcode_get_result(op); LLVMValueRef args[] = { - llvm_void_cast(cgen_get_var(var, ctx)), - cgen_const_string(istr(vcode_var_name(var))) + cgen_const_string(istr(vcode_get_ident(op))) }; - LLVMBuildCall(builder, llvm_fn("_link_signal"), args, ARRAY_LEN(args), ""); + LLVMValueRef shared = LLVMBuildCall(builder, llvm_fn("_link_signal"), + args, ARRAY_LEN(args), ""); + + LLVMValueRef r = LLVMGetUndef(llvm_signal_type()); + r = LLVMBuildInsertValue(builder, r, shared, 0, ""); + r = LLVMBuildInsertValue(builder, r, llvm_int32(0), 1, + cgen_reg_name(result)); + + ctx->regs[result] = r; } static void cgen_op(int i, cgen_ctx_t *ctx) @@ -3881,7 +3918,7 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_sched_waveform") == 0) { LLVMTypeRef args[] = { - LLVMInt32Type(), + LLVMPointerType(llvm_signal_shared_struct(), 0), LLVMInt32Type(), llvm_void_ptr(), LLVMInt32Type(), @@ -3894,7 +3931,7 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_sched_waveform_s") == 0) { LLVMTypeRef args[] = { - LLVMInt32Type(), + LLVMPointerType(llvm_signal_shared_struct(), 0), LLVMInt32Type(), LLVMInt64Type(), LLVMInt64Type(), @@ -3906,7 +3943,7 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_sched_event") == 0) { LLVMTypeRef args[] = { - LLVMInt32Type(), + LLVMPointerType(llvm_signal_shared_struct(), 0), LLVMInt32Type(), LLVMInt32Type(), LLVMInt32Type() @@ -3926,7 +3963,7 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_init_signal") == 0) { LLVMTypeRef args[] = { - LLVMInt32Type(), + LLVMPointerType(llvm_signal_shared_struct(), 0), LLVMInt32Type(), llvm_void_ptr(), }; @@ -3991,11 +4028,11 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_link_signal") == 0) { LLVMTypeRef args[] = { - llvm_void_ptr(), LLVMPointerType(LLVMInt8Type(), 0) }; + LLVMTypeRef result_type = LLVMPointerType(llvm_signal_shared_struct(), 0); fn = LLVMAddFunction(module, "_link_signal", - LLVMFunctionType(LLVMVoidType(), + LLVMFunctionType(result_type, args, ARRAY_LEN(args), false)); } else if (strcmp(name, "_assert_fail") == 0) { @@ -4216,7 +4253,7 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_test_net_flag") == 0) { LLVMTypeRef args[] = { - LLVMInt32Type(), + LLVMPointerType(llvm_signal_shared_struct(), 0), LLVMInt32Type(), LLVMInt32Type(), LLVMInt32Type() diff --git a/src/eval.c b/src/eval.c index 3d33b0cd..8d497d83 100644 --- a/src/eval.c +++ b/src/eval.c @@ -321,6 +321,9 @@ static void eval_dump(text_buf_t *tb, value_t *value, type_t type) } tb_printf(tb, "}"); break; + case VALUE_SIGNAL: + tb_printf(tb, "$<>"); + break; default: tb_printf(tb, "<%d>", value->kind); break; @@ -1132,6 +1135,11 @@ static void eval_op_wrap(int op, eval_state_t *state) value_t *dst = eval_get_reg(vcode_get_result(op), state); value_t *src = eval_get_reg(vcode_get_arg(op, 0), state); + if (src->kind == VALUE_SIGNAL) { + dst->kind = VALUE_SIGNAL; + return; + } + EVAL_ASSERT_VALUE(op, src, VALUE_POINTER); dst->kind = VALUE_UARRAY; @@ -1874,8 +1882,8 @@ static void eval_op_debug_out(int op, eval_state_t *state) static void eval_op_link_signal(int op, eval_state_t *state) { - value_t *var = eval_get_var(vcode_get_address(op), state->context); - var->kind = VALUE_SIGNAL; + value_t *dst = eval_get_reg(vcode_get_result(op), state); + dst->kind = VALUE_SIGNAL; } static void eval_vcode(eval_state_t *state) diff --git a/src/lower.c b/src/lower.c index 4191609e..e0138df9 100644 --- a/src/lower.c +++ b/src/lower.c @@ -5032,12 +5032,20 @@ static void lower_signal_decl(tree_t decl) const bool from_package = tree_flags(decl) & TREE_F_PACKAGE_SIGNAL; assert(!(is_package_signal && from_package)); - vcode_var_t var = emit_var(lower_signal_type(type), - lower_bounds(type), + vcode_type_t signal_type = lower_signal_type(type); + vcode_var_t var = emit_var(signal_type, lower_bounds(type), name, VAR_SIGNAL); lower_put_vcode_obj(decl, var, lower_bottom_scope()); - emit_link_signal(var); + vcode_reg_t shared = VCODE_INVALID_REG; + if (vtype_kind(signal_type) == VCODE_TYPE_UARRAY) { + shared = emit_link_signal(name, vtype_elem(signal_type)); + emit_store(lower_wrap(type, shared), var); + } + else { + shared = emit_link_signal(name, signal_type); + emit_store(shared, var); + } tree_t value = tree_value(decl); vcode_reg_t init_reg = lower_expr(value, EXPR_RVALUE); @@ -5054,8 +5062,9 @@ static void lower_signal_decl(tree_t decl) resolution = NULL; } - emit_init_signal(emit_load(var), init_reg, resolution); + emit_init_signal(shared, init_reg, resolution); +#if 0 return; vcode_type_t stype; @@ -5101,6 +5110,7 @@ static void lower_signal_decl(tree_t decl) if (shadow != VCODE_INVALID_VAR) emit_resolved_address(shadow, sig); +#endif } static void lower_file_decl(tree_t decl) @@ -5271,11 +5281,20 @@ static void lower_ports(tree_t unit) bounds = lower_bounds(type); } - vcode_var_t var = emit_var(lower_signal_type(type), - lower_bounds(type), - tree_ident(p), VAR_SIGNAL); + ident_t name = tree_ident(p); + + vcode_type_t signal_type = lower_signal_type(type); + vcode_var_t var = emit_var(signal_type, lower_bounds(type), + name, VAR_SIGNAL); lower_put_vcode_obj(p, var | 0x80000000, top_scope); - emit_link_signal(var); + + if (vtype_kind(signal_type) == VCODE_TYPE_UARRAY) { + vcode_reg_t data = emit_link_signal(name, vtype_elem(signal_type)); + vcode_reg_t wrap = lower_wrap(type, data); + emit_store(wrap, var); + } + else + emit_store(emit_link_signal(name, signal_type), var); #if 0 continue; diff --git a/src/rt/rtkern.c b/src/rt/rtkern.c index 0e46d276..01b1f9ba 100644 --- a/src/rt/rtkern.c +++ b/src/rt/rtkern.c @@ -177,13 +177,25 @@ typedef struct _rt_nexus { void *resolved; } rt_nexus_t; +// The code generator knows the layout of this struct typedef struct { - e_node_t enode; - uint32_t width; - uint32_t size; - uint32_t n_nexus; - uint8_t *displaced; - rt_nexus_t **nexus; // TODO: flatten this + uint32_t id; + uint32_t __pad; // TODO: put flags here + union { + uint8_t *displaced; + uint64_t resolved; // TODO: not used + }; +} sig_shared_t; + +STATIC_ASSERT(sizeof(sig_shared_t) == 16); + +typedef struct { + sig_shared_t shared; + e_node_t enode; + uint32_t width; + uint32_t size; + uint32_t n_nexus; + rt_nexus_t **nexus; // TODO: flatten this } rt_signal_t; typedef struct rt_scope_s { @@ -576,11 +588,10 @@ void _sched_process(int64_t delay) } DLLEXPORT -void _sched_waveform_s(uint32_t sid, uint32_t offset, uint64_t scalar, +void _sched_waveform_s(sig_shared_t *ss, uint32_t offset, uint64_t scalar, int64_t after, int64_t reject) { - RT_ASSERT(sid < active_proc->scope->n_signals); - rt_signal_t *s = &(active_proc->scope->signals[sid]); + rt_signal_t *s = container_of(ss, rt_signal_t, shared); TRACE("_sched_waveform_s %s+%d value=%"PRIi64" after=%s reject=%s", istr(e_path(s->enode)), offset, scalar, fmt_time(after), @@ -600,11 +611,10 @@ void _sched_waveform_s(uint32_t sid, uint32_t offset, uint64_t scalar, } DLLEXPORT -void _sched_waveform(uint32_t sid, int32_t offset, void *values, int32_t len, - int64_t after, int64_t reject) +void _sched_waveform(sig_shared_t *ss, uint32_t offset, void *values, + int32_t len, int64_t after, int64_t reject) { - RT_ASSERT(sid < active_proc->scope->n_signals); - rt_signal_t *s = &(active_proc->scope->signals[sid]); + rt_signal_t *s = container_of(ss, rt_signal_t, shared); TRACE("_sched_waveform %s+%d value=%s len=%d after=%s reject=%s", istr(e_path(s->enode)), offset, fmt_values(values, len * s->size), @@ -630,10 +640,10 @@ void _sched_waveform(uint32_t sid, int32_t offset, void *values, int32_t len, } DLLEXPORT -void _sched_event(uint32_t sid, uint32_t offset, int32_t count, int32_t flags) +void _sched_event(sig_shared_t *ss, uint32_t offset, int32_t count, + int32_t flags) { - RT_ASSERT(sid < active_proc->scope->n_signals); - rt_signal_t *s = &(active_proc->scope->signals[sid]); + rt_signal_t *s = container_of(ss, rt_signal_t, shared); TRACE("_sched_event %s+%d count=%d flags=%d proc %s", istr(e_path(s->enode)), offset, count, flags, istr(e_path(active_proc->source))); @@ -793,24 +803,14 @@ void _needs_last_value(const int32_t *nids, int32_t n) } DLLEXPORT -void _link_signal(void *data, const char *name) +sig_shared_t *_link_signal(const char *name) { TRACE("_link_signal %s", name); - struct { - uint32_t id; - uint32_t offset; - void *resolved; - } *sigdata = data; - for (unsigned i = 0; i < active_scope->n_signals; i++) { rt_signal_t *signal = &(active_scope->signals[i]); - if (icmp(e_ident(signal->enode), name)) { - sigdata->id = i; - sigdata->offset = 0; - sigdata->resolved = signal->displaced; - return; - } + if (icmp(e_ident(signal->enode), name)) + return &(signal->shared); } fatal("failed to link signal %s in scope %s", name, @@ -842,10 +842,9 @@ void _init_nexus(uint32_t nid, const uint8_t *values) } DLLEXPORT -void _init_signal(uint32_t sid, int32_t offset, const uint8_t *values) +void _init_signal(sig_shared_t *ss, int32_t offset, const uint8_t *values) { - RT_ASSERT(sid < active_scope->n_signals); - rt_signal_t *s = &(active_scope->signals[sid]); + rt_signal_t *s = container_of(ss, rt_signal_t, shared); TRACE("_init_signal %s values=%s", istr(e_path(s->enode)), fmt_values(values, s->size * s->width)); @@ -1485,11 +1484,10 @@ int64_t _last_event(const int32_t *nids, int32_t n) } DLLEXPORT -int32_t _test_net_flag(uint32_t sid, uint32_t offset, int32_t count, +int32_t _test_net_flag(sig_shared_t *ss, uint32_t offset, int32_t count, int32_t flag) { - RT_ASSERT(sid < active_proc->scope->n_signals); - rt_signal_t *s = &(active_proc->scope->signals[sid]); + rt_signal_t *s = container_of(ss, rt_signal_t, shared); TRACE("_test_net_flag %s offset=%d count=%d flag=%d", istr(e_path(s->enode)), offset, count, flag); @@ -1971,7 +1969,7 @@ static void rt_setup_scopes_recur(e_node_t e, unsigned *next_scope, for (int j = 0; j < r->n_nexus; j++) r->nexus[j] = &(nexus[e_pos(e_nexus(s, j))]); - r->displaced = r->nexus[0]->resolved; // XXX + r->shared.displaced = r->nexus[0]->resolved; // XXX } } diff --git a/src/vcode.c b/src/vcode.c index b81fcc50..c47634eb 100644 --- a/src/vcode.c +++ b/src/vcode.c @@ -38,8 +38,7 @@ DECLARE_AND_DEFINE_ARRAY(vcode_type); || x == VCODE_OP_CAST || x == VCODE_OP_CONST_RECORD) #define OP_HAS_ADDRESS(x) \ (x == VCODE_OP_LOAD || x == VCODE_OP_STORE || x == VCODE_OP_INDEX \ - || x == VCODE_OP_RESOLVED_ADDRESS || x == VCODE_OP_VAR_UPREF \ - || x == VCODE_OP_LINK_SIGNAL) + || x == VCODE_OP_RESOLVED_ADDRESS || x == VCODE_OP_VAR_UPREF) #define OP_HAS_SUBKIND(x) \ (x == VCODE_OP_SCHED_EVENT || x == VCODE_OP_BOUNDS \ || x == VCODE_OP_VEC_LOAD || x == VCODE_OP_BIT_VEC_OP \ @@ -49,6 +48,8 @@ DECLARE_AND_DEFINE_ARRAY(vcode_type); (x == VCODE_OP_FCALL || x == VCODE_OP_NESTED_FCALL \ || x == VCODE_OP_PCALL || x == VCODE_OP_RESUME \ || x == VCODE_OP_NESTED_PCALL || x == VCODE_OP_NESTED_RESUME) +#define OP_HAS_IDENT(x) \ + (x == VCODE_OP_LINK_SIGNAL) #define OP_HAS_REAL(x) \ (x == VCODE_OP_CONST_REAL) #define OP_HAS_VALUE(x) \ @@ -92,6 +93,7 @@ typedef struct { vcode_type_t type; // OP_HAS_TYPE union { ident_t func; // OP_HAS_FUNC + ident_t ident; // OP_HAS_IDENT vcode_var_t address; // OP_HAS_ADDRESS unsigned subkind; // OP_HAS_SUBKIND }; @@ -885,6 +887,13 @@ ident_t vcode_get_func(int op) return o->func; } +ident_t vcode_get_ident(int op) +{ + op_t *o = vcode_op_data(op); + assert(OP_HAS_IDENT(o->kind)); + return o->ident; +} + const vcode_res_fn_t *vcode_get_resolution(int op) { op_t *o = vcode_op_data(op); @@ -2221,8 +2230,10 @@ void vcode_dump_with_mark(int mark_op, vcode_dump_fn_t callback, void *arg) case VCODE_OP_LINK_SIGNAL: { - printf("%s ", vcode_op_string(op->kind)); - vcode_dump_var(op->address, 0); + col += vcode_dump_reg(op->result); + col += color_printf(" := %s $white$%s$$", + vcode_op_string(op->kind), istr(op->ident)); + vcode_dump_result_type(col, op); } break; } @@ -4265,6 +4276,9 @@ void emit_init_signal(vcode_reg_t signal, vcode_reg_t value, vcode_add_arg(op, signal); vcode_add_arg(op, value); op->resolution = resolution; + + VCODE_ASSERT(vcode_reg_kind(signal) == VCODE_TYPE_SIGNAL, + "argument to init signal is not a signal"); } void emit_alloc_driver(vcode_reg_t all_nets, vcode_reg_t all_length, @@ -4995,10 +5009,15 @@ void emit_debug_info(const loc_t *loc) vcode_block_data()->last_loc = *loc; } -void emit_link_signal(vcode_var_t var) +vcode_reg_t emit_link_signal(ident_t name, vcode_type_t type) { op_t *op = vcode_add_op(VCODE_OP_LINK_SIGNAL); - op->address = var; + op->ident = name; + + VCODE_ASSERT(vtype_kind(type) == VCODE_TYPE_SIGNAL, + "link signal type must be a signal"); + + return (op->result = vcode_add_reg(type)); } static void vcode_write_unit(vcode_unit_t unit, fbuf_t *f, @@ -5044,7 +5063,7 @@ static void vcode_write_unit(vcode_unit_t unit, fbuf_t *f, write_u32(op->type, f); if (OP_HAS_ADDRESS(op->kind)) write_u32(op->address, f); - if (OP_HAS_FUNC(op->kind)) + if (OP_HAS_FUNC(op->kind) || OP_HAS_IDENT(op->kind)) ident_write(op->func, ident_wr_ctx); if (OP_HAS_SUBKIND(op->kind)) write_u8(op->subkind, f); @@ -5265,7 +5284,7 @@ static bool vcode_read_unit(fbuf_t *f, ident_rd_ctx_t ident_rd_ctx, op->type = read_u32(f); if (OP_HAS_ADDRESS(op->kind)) op->address = read_u32(f); - if (OP_HAS_FUNC(op->kind)) + if (OP_HAS_FUNC(op->kind) || OP_HAS_IDENT(op->kind)) op->func = ident_read(ident_rd_ctx); if (OP_HAS_SUBKIND(op->kind)) op->subkind = read_u8(f); diff --git a/src/vcode.h b/src/vcode.h index 72222767..abc27524 100644 --- a/src/vcode.h +++ b/src/vcode.h @@ -321,6 +321,7 @@ const loc_t *vcode_get_loc(int op); const char *vcode_get_hint(int op); vcode_block_t vcode_get_target(int op, int nth); vcode_var_t vcode_get_address(int op); +ident_t vcode_get_ident(int op); int vcode_count_args(int op); vcode_reg_t vcode_get_arg(int op, int arg); vcode_type_t vcode_get_type(int op); @@ -489,6 +490,6 @@ vcode_reg_t emit_physical_map(ident_t name, size_t nelems, void emit_debug_info(const loc_t *loc); vcode_reg_t emit_range_null(vcode_reg_t left, vcode_reg_t right, vcode_reg_t dir); -void emit_link_signal(vcode_var_t var); +vcode_reg_t emit_link_signal(ident_t name, vcode_type_t type); #endif // _VCODE_H diff --git a/test/group/signal3.vhd b/test/group/signal3.vhd new file mode 100644 index 00000000..e1b5be6b --- /dev/null +++ b/test/group/signal3.vhd @@ -0,0 +1,37 @@ +entity signal3 is +end entity; + +architecture test of signal3 is + signal v : bit_vector(3 downto 0); +begin + + proc1: process is + begin + assert not v'active; + assert not v'event; + wait for 1 ns; + v(2) <= '1'; + wait for 0 ns; + assert v'event and v'active; + wait; + end process; + + proc2: process is + begin + wait for 1 ns; + wait for 0 ns; + assert v'event and v'active; + wait for 1 ns; + v(0) <= '1'; + assert not v'event; + wait for 0 ns; + assert v'event and v'active; + wait for 1 ns; + assert not v'event; + v(0) <= '1'; + wait for 0 ns; + assert not v'event and v'active; + wait; + end process; + +end architecture; diff --git a/test/test_elab.c b/test/test_elab.c index 6c9ecc16..5e4af819 100644 --- a/test/test_elab.c +++ b/test/test_elab.c @@ -892,8 +892,6 @@ START_TEST(test_signal3) e_node_t root = run_elab(); check_elab(root); - e_dump(root); - e_node_t proc1 = e_proc(e_scope(root, 0), 0); e_node_t proc2 = e_proc(e_scope(root, 0), 1); -- 2.39.2