From 967f50a12fd25169b303dce3fedf6667ef7d76f4 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 13 Aug 2023 10:18:21 +0100 Subject: [PATCH] Collapse output ports in restricted circumstances --- src/driver.c | 118 +++++++++++++++++++++++++++++++++++ src/driver.h | 1 + src/elab.c | 22 +++---- src/lower.c | 52 ++++++++++++--- src/lower.h | 3 +- src/mask.c | 40 ++++++++++++ src/mask.h | 1 + test/driver/unique1.vhd | 34 ++++++++++ test/regress/gold/wave3.dump | 22 +------ test/test_driver.c | 33 +++++++++- test/test_lower.c | 10 ++- test/test_misc.c | 4 ++ 12 files changed, 290 insertions(+), 50 deletions(-) create mode 100644 test/driver/unique1.vhd diff --git a/src/driver.c b/src/driver.c index 6e469e6f4..54c08c2af 100644 --- a/src/driver.c +++ b/src/driver.c @@ -20,9 +20,11 @@ #include "driver.h" #include "hash.h" #include "ident.h" +#include "mask.h" #include "option.h" #include "phase.h" #include "tree.h" +#include "type.h" #include #include @@ -327,6 +329,122 @@ driver_info_t *get_drivers(driver_set_t *ds, tree_t what) return hash_get(ds->map, what); } +bool has_unique_driver(driver_set_t *ds, tree_t what) +{ + // True if signal has exactly one driver for each sub-element + + driver_info_t *di = get_drivers(ds, what); + + if (di == NULL) + return false; + + // First pass: look for assignments to the full signal + + bool saw_ref = false, saw_multiple = false; + tree_t proc = di->where; + for (driver_info_t *it = di; it; it = it->chain_decl) { + if (it->where != proc) + saw_multiple = true; + else if (tree_kind(it->prefix) == T_REF) + saw_ref = true; + } + + if (saw_ref && !saw_multiple) + return true; + + type_t type = tree_type(what); + int64_t length = 0, left = 0, right = 0; + range_kind_t rkind = RANGE_ERROR; + if (type_is_array(type) && dimension_of(type) == 1) { + tree_t r = range_of(type, 0); + if (folded_length(r, &length)) { + left = assume_int(tree_left(r)); + right = assume_int(tree_right(r)); + rkind = tree_subkind(r); + } + } + else if (type_is_record(type)) + length = type_fields(type); + + if (length == 0) + return false; + + // Second pass: look for assignments to disjoint sub-elements + + bit_mask_t mask = {}; + mask_init(&mask, length); + + bool covered = false; + for (driver_info_t *it = di; it; it = it->chain_decl) { + const tree_kind_t kind = tree_kind(it->prefix); + if (kind != T_ARRAY_REF && kind != T_ARRAY_SLICE && kind != T_RECORD_REF) + goto out_free; + + tree_t value = tree_value(it->prefix); + if (tree_kind(value) != T_REF) + goto out_free; + + assert(tree_ref(value) == what); + + switch (kind) { + case T_ARRAY_REF: + { + assert(tree_params(it->prefix) == 1); + tree_t p0 = tree_value(tree_param(it->prefix, 0)); + + int64_t ival; + if (!folded_int(p0, &ival)) + goto out_free; + + const int zero = rkind == RANGE_TO ? ival - left : ival - right; + if (mask_test(&mask, zero)) + goto out_free; + + mask_set(&mask, zero); + } + break; + + case T_ARRAY_SLICE: + { + tree_t r = tree_range(it->prefix, 0); + + int64_t low, high; + if (!folded_bounds(r, &low, &high) || high < low) + goto out_free; + + const int count = high - low + 1; + const int zero = rkind == RANGE_TO ? low - left : low - right; + + if (mask_test_range(&mask, zero, count)) + goto out_free; + + mask_set_range(&mask, zero, count); + } + break; + + case T_RECORD_REF: + { + const int pos = tree_pos(tree_ref(it->prefix)); + + if (mask_test(&mask, pos)) + goto out_free; + + mask_set(&mask, pos); + } + break; + + default: + goto out_free; + } + } + + covered = (mask_popcount(&mask) == length); + + out_free: + mask_free(&mask); + return covered; +} + LCOV_EXCL_START void dump_drivers(driver_set_t *ds) { diff --git a/src/driver.h b/src/driver.h index 9de32550c..8a53c11bb 100644 --- a/src/driver.h +++ b/src/driver.h @@ -33,6 +33,7 @@ typedef struct _driver_info { driver_set_t *find_drivers(tree_t block); driver_info_t *get_drivers(driver_set_t *ds, tree_t what); +bool has_unique_driver(driver_set_t *ds, tree_t what); void free_drivers(driver_set_t *ds); void dump_drivers(driver_set_t *ds); diff --git a/src/elab.c b/src/elab.c index 98c7e1847..42d7afb9a 100644 --- a/src/elab.c +++ b/src/elab.c @@ -1241,10 +1241,20 @@ static void elab_inherit_context(elab_ctx_t *ctx, const elab_ctx_t *parent) ctx->inst = ctx->inst ?: parent->inst; } +static driver_set_t *elab_driver_set(const elab_ctx_t *ctx) +{ + if (ctx->drivers != NULL) + return ctx->drivers; + else if (ctx->parent != NULL) + return elab_driver_set(ctx->parent); + else + return NULL; +} + static void elab_lower(tree_t b, elab_ctx_t *ctx) { ctx->lowered = lower_instance(ctx->registry, ctx->parent->lowered, - ctx->cover, b); + elab_driver_set(ctx), ctx->cover, b); if (ctx->cover != NULL) eval_alloc_cover_mem(ctx->jit, ctx->cover); @@ -1877,16 +1887,6 @@ static void elab_case_generate(tree_t t, const elab_ctx_t *ctx) elab_pop_scope(&new_ctx); } -static driver_set_t *elab_driver_set(const elab_ctx_t *ctx) -{ - if (ctx->drivers != NULL) - return ctx->drivers; - else if (ctx->parent != NULL) - return elab_driver_set(ctx->parent); - else - return NULL; -} - static void elab_process(tree_t t, const elab_ctx_t *ctx) { elab_external_names(t, ctx); diff --git a/src/lower.c b/src/lower.c index 94728a4de..02c25cd9b 100644 --- a/src/lower.c +++ b/src/lower.c @@ -5002,13 +5002,17 @@ static vcode_reg_t lower_default_value(lower_unit_t *lu, type_t type, return emit_address_of(lower_nested_default_value(lu, type)); } - assert(hint_reg != VCODE_INVALID_REG); - vcode_reg_t count_reg = lower_array_total_len(lu, type, VCODE_INVALID_REG); vcode_reg_t def_reg = lower_default_value(lu, elem_type, VCODE_INVALID_REG); + if (hint_reg == VCODE_INVALID_REG) { + vcode_type_t velem = lower_type(elem_type); + vcode_type_t vbounds = lower_bounds(elem_type); + hint_reg = emit_alloc(velem, vbounds, count_reg); + } + if (type_is_scalar(elem_type)) emit_memset(hint_reg, def_reg, count_reg); else { @@ -10714,6 +10718,8 @@ static void lower_map_signal_field_cb(lower_unit_t *lu, tree_t field, src_reg = emit_load_indirect(dst_ptr); else if (!args->is_const) src_reg = emit_load_indirect(src_ptr); + else if (have_uarray_ptr(src_ptr)) + src_reg = emit_load_indirect(src_ptr); else src_reg = src_ptr; @@ -11014,8 +11020,9 @@ static void lower_port_map(lower_unit_t *lu, tree_t block, tree_t map, } } -static bool lower_direct_mapped_port(lower_unit_t *lu, tree_t block, tree_t map, - hset_t *direct, hset_t **poison) +static bool lower_direct_mapped_port(lower_unit_t *lu, driver_set_t *ds, + tree_t block, tree_t map, hset_t *direct, + hset_t **poison) { tree_t port = NULL; int field = -1; @@ -11046,8 +11053,18 @@ static bool lower_direct_mapped_port(lower_unit_t *lu, tree_t block, tree_t map, assert(tree_kind(port) == T_PORT_DECL); const class_t class = tree_class(port); - if (class == C_SIGNAL && tree_subkind(port) != PORT_IN) - return false; + if (class == C_SIGNAL) { + switch (tree_subkind(port)) { + case PORT_IN: + break; // Always safe + case PORT_OUT: + if (!has_unique_driver(ds, port)) + return false; + break; + default: + return false; + } + } tree_t value = tree_value(map); @@ -11212,7 +11229,7 @@ static vcode_reg_t lower_constrain_port(lower_unit_t *lu, tree_t port, int pos, istr(tree_ident(port))); } -static void lower_ports(lower_unit_t *lu, tree_t block) +static void lower_ports(lower_unit_t *lu, driver_set_t *ds, tree_t block) { const int nports = tree_ports(block); const int nparams = tree_params(block); @@ -11227,7 +11244,8 @@ static void lower_ports(lower_unit_t *lu, tree_t block) for (int i = 0; i < nparams; i++) { tree_t p = tree_param(block, i); - if (collapse && lower_direct_mapped_port(lu, block, p, direct, &poison)) + if (collapse && lower_direct_mapped_port(lu, ds, block, + p, direct, &poison)) map_regs[i] = VCODE_INVALID_REG; else { tree_t value = tree_value(p); @@ -11253,6 +11271,19 @@ static void lower_ports(lower_unit_t *lu, tree_t block) lower_port_signal(lu, port, bounds_reg); else if (poison != NULL && hset_contains(poison, port)) lower_port_signal(lu, port, bounds_reg); + else if (tree_class(port) == C_SIGNAL && tree_subkind(port) != PORT_IN) { + // Any drivers for collapsed output ports must take their + // initial value from the port declaration + vcode_reg_t def_reg; + if (tree_has_value(port)) + def_reg = lower_rvalue(lu, tree_value(port)); + else + def_reg = lower_default_value(lu, type, VCODE_INVALID_REG); + + vcode_reg_t nets_reg = lower_port_ref(lu, port); + lower_map_signal(lu, def_reg, nets_reg, type, type, + VCODE_INVALID_REG, port); + } } for (int i = 0; i < nparams; i++) { @@ -11730,7 +11761,8 @@ vcode_unit_t lower_thunk(lower_unit_t *parent, tree_t t) } lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, - cover_tagging_t *cover, tree_t block) + driver_set_t *ds, cover_tagging_t *cover, + tree_t block) { assert(tree_kind(block) == T_BLOCK); @@ -11753,7 +11785,7 @@ lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, lower_dependencies(block, tree_ref(hier)); lower_generics(lu, block); - lower_ports(lu, block); + lower_ports(lu, ds, block); lower_decls(lu, block); emit_return(VCODE_INVALID_REG); diff --git a/src/lower.h b/src/lower.h index 76c4ab46c..af9349de6 100644 --- a/src/lower.h +++ b/src/lower.h @@ -50,7 +50,8 @@ vcode_reg_t lower_lvalue(lower_unit_t *lu, tree_t expr); vcode_reg_t lower_rvalue(lower_unit_t *lu, tree_t expr); lower_unit_t *lower_instance(unit_registry_t *ur, lower_unit_t *parent, - cover_tagging_t *cover, tree_t block); + driver_set_t *ds, cover_tagging_t *cover, + tree_t block); void lower_process(lower_unit_t *parent, tree_t proc, driver_set_t *ds); vcode_unit_t lower_thunk(lower_unit_t *parent, tree_t fcall); vcode_unit_t lower_case_generate_thunk(lower_unit_t *parent, tree_t t); diff --git a/src/mask.c b/src/mask.c index a12bbce57..266c73c43 100644 --- a/src/mask.c +++ b/src/mask.c @@ -123,6 +123,46 @@ void mask_set_range(bit_mask_t *m, int start, int count) } } +bool mask_test_range(bit_mask_t *m, int start, int count) +{ + if (m->size <= 64) + return !!(m->bits & mask_for_range(start, start + count - 1)); + + if (count > 0 && start % 64 != 0) { + // Pre-loop: test range of bits in first 64-bit word + const int low = start % 64; + const int high = MIN(low + count - 1, 63); + const int nbits = high - low + 1; + + if (m->ptr[start / 64] & mask_for_range(low, high)) + return true; + + start += nbits; + count -= nbits; + } + + if (count > 0) { + // Main loop: test complete 64-bit words + for (; count >= 64; count -= 64, start += 64) { + if (m->ptr[start / 64]) + return true; + } + } + + if (count > 0) { + // Post-loop: test range of bits in last 64-bit word + assert(start % 64 == 0); + const int high = MIN(count - 1, 63); + + if (m->ptr[start / 64] & mask_for_range(0, high)) + return true; + + assert(count == high + 1); + } + + return false; +} + int mask_popcount(bit_mask_t *m) { if (m->size > 64) { diff --git a/src/mask.h b/src/mask.h index a5bb79951..1d5809921 100644 --- a/src/mask.h +++ b/src/mask.h @@ -62,6 +62,7 @@ void mask_init(bit_mask_t *m, size_t size); void mask_free(bit_mask_t *m); void mask_clear_range(bit_mask_t *m, int start, int count); void mask_set_range(bit_mask_t *m, int start, int count); +bool mask_test_range(bit_mask_t *m, int start, int count); int mask_popcount(bit_mask_t *m); void mask_setall(bit_mask_t *m); void mask_clearall(bit_mask_t *m); diff --git a/test/driver/unique1.vhd b/test/driver/unique1.vhd new file mode 100644 index 000000000..037c4c291 --- /dev/null +++ b/test/driver/unique1.vhd @@ -0,0 +1,34 @@ +entity unique1 is +end entity; + +architecture test of unique1 is + type t_rec is record + a, b : integer; + c : bit_vector(1 to 3); + end record; + + signal s1 : bit_vector(1 downto 0); + signal s2 : bit_vector(2 downto 0); + signal s3 : bit_vector(7 downto 3); + signal s4 : t_rec; + signal s5 : t_rec; +begin + + s1(1) <= '1'; + s1(0) <= '0'; + + s2(1) <= '1'; + s2(0) <= '0'; + + s3(7 downto 7) <= "1"; + s3(6 downto 4) <= "101"; + s3(3) <= '0'; + + s4.a <= 5; + s4.b <= 7; + s4.c <= "101"; + + s5.a <= 5; + s5.b <= 7; + s5.c(1 to 2) <= "11"; +end architecture; diff --git a/test/regress/gold/wave3.dump b/test/regress/gold/wave3.dump index 807ccfe01..de0e86f66 100644 --- a/test/regress/gold/wave3.dump +++ b/test/regress/gold/wave3.dump @@ -1,10 +1,10 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end +$comment wave3.sub_i.y[7:0] is aliased to y[7:0] $end #0 wave3.gen(3).g 10000000000000000000000000000000 #0 wave3.gen(2).g 10000000000000000000000000000000 #0 wave3.gen(1).g 10000000000000000000000000000000 #0 wave3.sub_i.ctr2[15:0] 0000000000000000 #0 wave3.sub_i.ctr[3:18] 0000000000000000 -#0 wave3.sub_i.y[7:0] UUUUUUUU #0 wave3.a_block.c nul #0 wave3.a_block.c 'a' #0 wave3.a_block.i 00000000000000000000000000000000 @@ -24,7 +24,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #1000 wave3.t 20 US #4000000 wave3.s2 two #5000000 wave3.y[7:0] 10101010 -#5000000 wave3.sub_i.y[7:0] 10101010 #20000000 wave3.a_block.i 00000000000000000000000000000001 #20000000 wave3.a_block.c 'b' #20000000 wave3.sub_i.ctr[3:18] 0000000000000001 @@ -34,7 +33,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #40000000 wave3.a_block.c 'c' #40000000 wave3.a_block.i 00000000000000000000000000000010 #50000000 wave3.x[7:0] 01010101 -#55000000 wave3.sub_i.y[7:0] 01010101 #55000000 wave3.y[7:0] 01010101 #60000000 wave3.a_block.i 00000000000000000000000000000011 #60000000 wave3.a_block.c 'a' @@ -52,7 +50,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #100000000 wave3.x[7:0] 10101010 #100000000 wave3.z x #105000000 wave3.y[7:0] 10101010 -#105000000 wave3.sub_i.y[7:0] 10101010 #120000000 wave3.sub_i.ctr2[15:0] 0000000000000110 #120000000 wave3.sub_i.ctr[3:18] 0000000000000110 #120000000 wave3.a_block.c 'a' @@ -63,7 +60,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #140000000 wave3.sub_i.ctr2[15:0] 0000000000000111 #150000000 wave3.x[7:0] 01010101 #150000000 wave3.s two -#155000000 wave3.sub_i.y[7:0] 01010101 #155000000 wave3.y[7:0] 01010101 #160000000 wave3.sub_i.ctr2[15:0] 0000000000001000 #160000000 wave3.sub_i.ctr[3:18] 0000000000001000 @@ -80,7 +76,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #200000000 wave3.x[7:0] 10101010 #200000000 wave3.z h #205000000 wave3.y[7:0] 10101010 -#205000000 wave3.sub_i.y[7:0] 10101010 #220000000 wave3.a_block.i 00000000000000000000000000001011 #220000000 wave3.a_block.c 'c' #220000000 wave3.sub_i.ctr[3:18] 0000000000001011 @@ -90,7 +85,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #240000000 wave3.a_block.c 'a' #240000000 wave3.a_block.i 00000000000000000000000000001100 #250000000 wave3.x[7:0] 01010101 -#255000000 wave3.sub_i.y[7:0] 01010101 #255000000 wave3.y[7:0] 01010101 #260000000 wave3.a_block.i 00000000000000000000000000001101 #260000000 wave3.a_block.c 'b' @@ -107,7 +101,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #300000000 wave3.x[7:0] 10101010 #300000000 wave3.z z #305000000 wave3.y[7:0] 10101010 -#305000000 wave3.sub_i.y[7:0] 10101010 #320000000 wave3.sub_i.ctr2[15:0] 0000000000010000 #320000000 wave3.sub_i.ctr[3:18] 0000000000010000 #320000000 wave3.a_block.c 'b' @@ -117,7 +110,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #340000000 wave3.sub_i.ctr[3:18] 0000000000010001 #340000000 wave3.sub_i.ctr2[15:0] 0000000000010001 #350000000 wave3.x[7:0] 01010101 -#355000000 wave3.sub_i.y[7:0] 01010101 #355000000 wave3.y[7:0] 01010101 #360000000 wave3.sub_i.ctr2[15:0] 0000000000010010 #360000000 wave3.sub_i.ctr[3:18] 0000000000010010 @@ -134,7 +126,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #400000000 wave3.x[7:0] 10101010 #400000000 wave3.z l #405000000 wave3.y[7:0] 10101010 -#405000000 wave3.sub_i.y[7:0] 10101010 #420000000 wave3.a_block.i 00000000000000000000000000010101 #420000000 wave3.a_block.c 'a' #420000000 wave3.sub_i.ctr[3:18] 0000000000010101 @@ -144,7 +135,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #440000000 wave3.a_block.c 'b' #440000000 wave3.a_block.i 00000000000000000000000000010110 #450000000 wave3.x[7:0] 01010101 -#455000000 wave3.sub_i.y[7:0] 01010101 #455000000 wave3.y[7:0] 01010101 #460000000 wave3.a_block.i 00000000000000000000000000010111 #460000000 wave3.a_block.c 'c' @@ -161,7 +151,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #500000000 wave3.x[7:0] 10101010 #500000000 wave3.z - #505000000 wave3.y[7:0] 10101010 -#505000000 wave3.sub_i.y[7:0] 10101010 #520000000 wave3.sub_i.ctr2[15:0] 0000000000011010 #520000000 wave3.sub_i.ctr[3:18] 0000000000011010 #520000000 wave3.a_block.c 'c' @@ -171,7 +160,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #540000000 wave3.sub_i.ctr[3:18] 0000000000011011 #540000000 wave3.sub_i.ctr2[15:0] 0000000000011011 #550000000 wave3.x[7:0] 01010101 -#555000000 wave3.sub_i.y[7:0] 01010101 #555000000 wave3.y[7:0] 01010101 #560000000 wave3.sub_i.ctr2[15:0] 0000000000011100 #560000000 wave3.sub_i.ctr[3:18] 0000000000011100 @@ -188,7 +176,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #600000000 wave3.x[7:0] 10101010 #600000000 wave3.z 1 #605000000 wave3.y[7:0] 10101010 -#605000000 wave3.sub_i.y[7:0] 10101010 #620000000 wave3.a_block.i 00000000000000000000000000011111 #620000000 wave3.a_block.c 'b' #620000000 wave3.sub_i.ctr[3:18] 0000000000011111 @@ -198,7 +185,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #640000000 wave3.a_block.c 'c' #640000000 wave3.a_block.i 00000000000000000000000000100000 #650000000 wave3.x[7:0] 01010101 -#655000000 wave3.sub_i.y[7:0] 01010101 #655000000 wave3.y[7:0] 01010101 #660000000 wave3.a_block.i 00000000000000000000000000100001 #660000000 wave3.a_block.c 'a' @@ -214,7 +200,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #700000000 wave3.sub_i.ctr2[15:0] 0000000000100011 #700000000 wave3.x[7:0] 10101010 #705000000 wave3.y[7:0] 10101010 -#705000000 wave3.sub_i.y[7:0] 10101010 #720000000 wave3.sub_i.ctr2[15:0] 0000000000100100 #720000000 wave3.sub_i.ctr[3:18] 0000000000100100 #720000000 wave3.a_block.c 'a' @@ -224,7 +209,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #740000000 wave3.sub_i.ctr[3:18] 0000000000100101 #740000000 wave3.sub_i.ctr2[15:0] 0000000000100101 #750000000 wave3.x[7:0] 01010101 -#755000000 wave3.sub_i.y[7:0] 01010101 #755000000 wave3.y[7:0] 01010101 #760000000 wave3.sub_i.ctr2[15:0] 0000000000100110 #760000000 wave3.sub_i.ctr[3:18] 0000000000100110 @@ -240,7 +224,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #800000000 wave3.a_block.i 00000000000000000000000000101000 #800000000 wave3.x[7:0] 10101010 #805000000 wave3.y[7:0] 10101010 -#805000000 wave3.sub_i.y[7:0] 10101010 #820000000 wave3.a_block.i 00000000000000000000000000101001 #820000000 wave3.a_block.c 'c' #820000000 wave3.sub_i.ctr[3:18] 0000000000101001 @@ -250,7 +233,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #840000000 wave3.a_block.c 'a' #840000000 wave3.a_block.i 00000000000000000000000000101010 #850000000 wave3.x[7:0] 01010101 -#855000000 wave3.sub_i.y[7:0] 01010101 #855000000 wave3.y[7:0] 01010101 #860000000 wave3.a_block.i 00000000000000000000000000101011 #860000000 wave3.a_block.c 'b' @@ -266,7 +248,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #900000000 wave3.sub_i.ctr2[15:0] 0000000000101101 #900000000 wave3.x[7:0] 10101010 #905000000 wave3.y[7:0] 10101010 -#905000000 wave3.sub_i.y[7:0] 10101010 #920000000 wave3.sub_i.ctr2[15:0] 0000000000101110 #920000000 wave3.sub_i.ctr[3:18] 0000000000101110 #920000000 wave3.a_block.c 'b' @@ -276,7 +257,6 @@ $comment wave3.sub_i.x[7:0] is aliased to x[7:0] $end #940000000 wave3.sub_i.ctr[3:18] 0000000000101111 #940000000 wave3.sub_i.ctr2[15:0] 0000000000101111 #950000000 wave3.x[7:0] 01010101 -#955000000 wave3.sub_i.y[7:0] 01010101 #955000000 wave3.y[7:0] 01010101 #960000000 wave3.sub_i.ctr2[15:0] 0000000000110000 #960000000 wave3.sub_i.ctr[3:18] 0000000000110000 diff --git a/test/test_driver.c b/test/test_driver.c index 1dad6335d..bc6844bf3 100644 --- a/test/test_driver.c +++ b/test/test_driver.c @@ -99,7 +99,8 @@ START_TEST(test_sanity1) ck_assert_ptr_nonnull(g5p0di->chain_proc); ck_assert(g5p0di->tentative); - free_drivers(di); + ck_assert(has_unique_driver(ds, x)); + ck_assert(!has_unique_driver(ds, z)); free_drivers(ds); @@ -145,6 +146,35 @@ START_TEST(test_sanity2) } END_TEST +START_TEST(test_unique1) +{ + input_from_file(TESTDIR "/driver/unique1.vhd"); + + tree_t a = parse_check_and_simplify(T_ENTITY, T_ARCH); + + driver_set_t *ds = find_drivers(a); + + tree_t s1 = get_decl(a, "S1"); + ck_assert(has_unique_driver(ds, s1)); + + tree_t s2 = get_decl(a, "S2"); + ck_assert(!has_unique_driver(ds, s2)); + + tree_t s3 = get_decl(a, "S3"); + ck_assert(has_unique_driver(ds, s3)); + + tree_t s4 = get_decl(a, "S4"); + ck_assert(has_unique_driver(ds, s4)); + + tree_t s5 = get_decl(a, "S5"); + ck_assert(!has_unique_driver(ds, s5)); + + free_drivers(ds); + + fail_if_errors(); +} +END_TEST + Suite *get_driver_tests(void) { Suite *s = suite_create("driver"); @@ -152,6 +182,7 @@ Suite *get_driver_tests(void) TCase *tc = nvc_unit_test(); tcase_add_test(tc, test_sanity1); tcase_add_test(tc, test_sanity2); + tcase_add_test(tc, test_unique1); suite_add_tcase(s, tc); return s; diff --git a/test/test_lower.c b/test/test_lower.c index 3c5c45d4f..ddec455a0 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -4469,14 +4469,12 @@ START_TEST(test_directmap) { VCODE_OP_STORE, .name = "I" }, { VCODE_OP_VAR_UPREF, .hops = 1, .name = "Y" }, { VCODE_OP_LOAD_INDIRECT }, - { VCODE_OP_CONST, .value = 4 }, - { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_DEBUG_LOCUS }, - { VCODE_OP_CONST, .value = INT32_MIN }, - { VCODE_OP_CONST, .value = 0 }, - { VCODE_OP_INIT_SIGNAL }, + { VCODE_OP_ALIAS_SIGNAL }, { VCODE_OP_STORE, .name = "O" }, - { VCODE_OP_MAP_SIGNAL }, + { VCODE_OP_CONST, .value = INT32_MIN }, + { VCODE_OP_CONST, .value = 1 }, + { VCODE_OP_MAP_CONST }, { VCODE_OP_RETURN }, }; diff --git a/test/test_misc.c b/test/test_misc.c index fd75045b7..4374a0912 100644 --- a/test/test_misc.c +++ b/test/test_misc.c @@ -400,6 +400,8 @@ START_TEST(test_set_clear_range) bit_mask_t m; mask_init(&m, mask_size[_i]); + fail_if(mask_test_range(&m, 0, mask_size[_i])); + mask_set_range(&m, 1, 2); fail_if(mask_test(&m, 0)); @@ -407,6 +409,7 @@ START_TEST(test_set_clear_range) fail_unless(mask_test(&m, 2)); fail_if(mask_test(&m, 3)); ck_assert_int_eq(mask_popcount(&m), 2); + fail_unless(mask_test_range(&m, 0, 5)); if (mask_size[_i] > 64) { mask_set_range(&m, 70, 3); @@ -417,6 +420,7 @@ START_TEST(test_set_clear_range) fail_unless(mask_test(&m, 72)); fail_if(mask_test(&m, 73)); ck_assert_int_eq(mask_popcount(&m), 5); + fail_unless(mask_test_range(&m, 60, 20)); mask_clear_range(&m, 71, 2);