From 5dabcefd75d93cd2fbf76531d5b0df35074986f7 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 23 Jun 2021 11:23:31 +0800 Subject: [PATCH] Nexus is the new group --- src/cgen.c | 30 +++- src/rt/rtkern.c | 391 ++++++++++++++++++++++++++++-------------------- 2 files changed, 252 insertions(+), 169 deletions(-) diff --git a/src/cgen.c b/src/cgen.c index 059c66ea..763e6578 100644 --- a/src/cgen.c +++ b/src/cgen.c @@ -1859,10 +1859,18 @@ static void cgen_op_nets(int op, cgen_ctx_t *ctx) ctx->regs[result] = cgen_signal_nets(sig); LLVMSetValueName(ctx->regs[result], cgen_reg_name(result)); #else - LLVMValueRef display = cgen_display_upref(1, ctx); + LLVMValueRef display = cgen_display_upref(1, ctx); LLVMValueRef sig_struct = LLVMBuildStructGEP(builder, display, sig, ""); - ctx->regs[result] = LLVMBuildStructGEP(builder, sig_struct, 0, - cgen_reg_name(result)); + LLVMValueRef sid_ptr = LLVMBuildStructGEP(builder, sig_struct, 0, ""); + LLVMValueRef sid_val = LLVMBuildLoad(builder, sid_ptr, ""); + + LLVMTypeRef elems[] = { LLVMInt32Type(), LLVMInt32Type() }; + LLVMTypeRef sigptr_type = LLVMStructType(elems, 2, false); + + LLVMValueRef sigptr = LLVMGetUndef(sigptr_type); + sigptr = LLVMBuildInsertValue(builder, sigptr, sid_val, 0, ""); + ctx->regs[result] = LLVMBuildInsertValue(builder, sigptr, llvm_int32(0), 0, + cgen_reg_name(result)); #endif } @@ -1910,9 +1918,14 @@ static void cgen_op_sched_waveform(int op, cgen_ctx_t *ctx) else valptr = llvm_void_cast(value); + LLVMValueRef sigptr = cgen_get_arg(op, 0, ctx); + LLVMValueRef sid = LLVMBuildExtractValue(builder, sigptr, 0, "sid"); + LLVMValueRef offset = LLVMBuildExtractValue(builder, sigptr, 0, "offset"); + if (scalar != NULL) { LLVMValueRef args[] = { - llvm_void_cast(cgen_get_arg(op, 0, ctx)), + sid, + offset, scalar, cgen_get_arg(op, 4, ctx), cgen_get_arg(op, 3, ctx) @@ -1922,7 +1935,8 @@ static void cgen_op_sched_waveform(int op, cgen_ctx_t *ctx) } else { LLVMValueRef args[] = { - llvm_void_cast(cgen_get_arg(op, 0, ctx)), + sid, + offset, valptr, cgen_get_arg(op, 1, ctx), cgen_get_arg(op, 4, ctx), @@ -3813,7 +3827,8 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_sched_waveform") == 0) { LLVMTypeRef args[] = { - llvm_void_ptr(), + LLVMInt32Type(), + LLVMInt32Type(), llvm_void_ptr(), LLVMInt32Type(), LLVMInt64Type(), @@ -3825,7 +3840,8 @@ static LLVMValueRef cgen_support_fn(const char *name) } else if (strcmp(name, "_sched_waveform_s") == 0) { LLVMTypeRef args[] = { - llvm_void_ptr(), + LLVMInt32Type(), + LLVMInt32Type(), LLVMInt64Type(), LLVMInt64Type(), LLVMInt64Type() diff --git a/src/rt/rtkern.c b/src/rt/rtkern.c index fafb1076..c3265cc8 100644 --- a/src/rt/rtkern.c +++ b/src/rt/rtkern.c @@ -1,4 +1,4 @@ -//e +// // Copyright (C) 2011-2021 Nick Gasson // // This program is free software: you can redistribute it and/or modify @@ -71,6 +71,7 @@ typedef struct callback callback_t; typedef struct image_map image_map_t; typedef struct rt_loc rt_loc_t; typedef struct size_list size_list_t; +typedef struct _rt_nexus rt_nexus_t; // The code generator knows the layout of this struct typedef struct { @@ -113,7 +114,7 @@ struct event { uint32_t wakeup_gen; event_t *delta_chain; rt_proc_t *proc; - netgroup_t *group; + rt_nexus_t *nexus; timeout_fn_t timeout_fn; void *timeout_user; }; @@ -164,19 +165,28 @@ struct netgroup { watch_list_t *watching; }; -typedef struct { - e_node_t enode; - uint32_t width; - uint32_t size; - uint32_t n_drivers; - driver_t *drivers; - void *resolved; +typedef struct _rt_nexus { + e_node_t enode; + uint32_t width; + uint32_t size; + value_t *free_values; + uint64_t last_event; + sens_list_t *pending; + watch_list_t *watching; + value_t *forcing; + net_flags_t flags; + res_memo_t *resolution; + uint32_t n_drivers; + driver_t *drivers; + void *resolved; } rt_nexus_t; typedef struct { e_node_t enode; uint32_t width; uint32_t size; + uint32_t n_nexus; + rt_nexus_t **nexus; } rt_signal_t; // The code generator knows the layout of this struct @@ -302,19 +312,19 @@ static rt_alloc_stack_t sens_list_stack = NULL; static rt_alloc_stack_t watch_stack = NULL; static rt_alloc_stack_t callback_stack = NULL; -static netgroup_t **active_groups; -static unsigned n_active_groups = 0; +static rt_nexus_t **active_nexus; +static unsigned n_active_nexus = 0; static unsigned n_active_alloc = 0; static void deltaq_insert_proc(uint64_t delta, rt_proc_t *wake); -static void deltaq_insert_driver(uint64_t delta, netgroup_t *group, +static void deltaq_insert_driver(uint64_t delta, rt_nexus_t *nexus, rt_proc_t *driver); -static bool rt_sched_driver(netgroup_t *group, uint64_t after, +static bool rt_sched_driver(rt_nexus_t *nexus, uint64_t after, uint64_t reject, value_t *values); static void rt_sched_event(sens_list_t **list, netid_t first, netid_t last, rt_proc_t *proc, bool is_static); static void *rt_tmp_alloc(size_t sz); -static value_t *rt_alloc_value(netgroup_t *g); +static value_t *rt_alloc_value(rt_nexus_t *n); static tree_t rt_recall_decl(const char *name); static res_memo_t *rt_memo_resolution_fn(type_t type, resolution_fn_t fn); static void _tracef(const char *fmt, ...); @@ -348,22 +358,23 @@ static void _tracef(const char *fmt, ...); //////////////////////////////////////////////////////////////////////////////// // Utilities -static const char *fmt_group(const netgroup_t *g) +static const char *fmt_nexus(const rt_nexus_t *n) { static const size_t BUF_LEN = 512; char *buf = get_fmt_buf(BUF_LEN); +#if 0 const char *eptr = buf + BUF_LEN; char *p = buf; - p += checked_sprintf(p, eptr - p, "%s", istr(tree_ident(g->sig_decl))); + p += checked_sprintf(p, eptr - p, "%s", istr(tree_ident(n->sig_decl))); - groupid_t sig_group0 = netdb_lookup(netdb, tree_net(g->sig_decl, 0)); + groupid_t sig_group0 = netdb_lookup(netdb, tree_net(n->sig_decl, 0)); netid_t sig_net0 = groups[sig_group0].first; - int offset = g->first - sig_net0; + int offset = n->first - sig_net0; - const int length = g->length; - type_t type = tree_type(g->sig_decl); + const int length = n->length; + type_t type = tree_type(n->sig_decl); while (type_is_array(type)) { const int stride = type_width(type_elem(type)); const int ndims = dimension_of(type); @@ -391,13 +402,14 @@ static const char *fmt_group(const netgroup_t *g) type = type_elem(type); } +#endif return buf; } static const char *fmt_net(netid_t nid) { - return fmt_group(&(groups[netdb_lookup(netdb, nid)])); + return ""; //fmt_group(&(groups[netdb_lookup(netdb, nid)])); } static const char *fmt_values(const void *values, int length) @@ -548,18 +560,30 @@ void _sched_process(int64_t delay) } DLLEXPORT -void _sched_waveform_s(void *_nids, uint64_t scalar, +void _sched_waveform_s(uint32_t sid, uint32_t offset, uint64_t scalar, int64_t after, int64_t reject) { - const int32_t *nids = _nids; + RT_ASSERT(sid < n_signals); + rt_signal_t *s = &(signals[sid]); - TRACE("_sched_waveform_s %s value=%08x after=%s reject=%s", - fmt_net(nids[0]), scalar, fmt_time(after), fmt_time(reject)); + TRACE("_sched_waveform_s %s+%d value=%"PRIi64" after=%s reject=%s", + istr(e_path(s->enode)), offset, scalar, fmt_time(after), + fmt_time(reject)); if (unlikely(active_proc->postponed && (after == 0))) fatal("postponed process %s cannot cause a delta cycle", istr(e_path(active_proc->source))); + assert(offset == 0); + rt_nexus_t *n = s->nexus[0]; + + value_t *values_copy = rt_alloc_value(n); + values_copy->qwords[0] = scalar; + + if (!rt_sched_driver(n, after, reject, values_copy)) + deltaq_insert_driver(after, n, active_proc); + +#if 0 const netid_t nid = nids[0]; if (likely(nid != NETID_INVALID)) { netgroup_t *g = &(groups[netdb_lookup(netdb, nid)]); @@ -570,12 +594,24 @@ void _sched_waveform_s(void *_nids, uint64_t scalar, if (!rt_sched_driver(g, after, reject, values_copy)) deltaq_insert_driver(after, g, active_proc); } +#endif } DLLEXPORT -void _sched_waveform(void *_nids, void *values, int32_t n, +void _sched_waveform(uint32_t sid, uint32_t offset, void *values, int32_t len, int64_t after, int64_t reject) { + RT_ASSERT(sid < n_nexus); + rt_signal_t *s = &(signals[sid]); + + TRACE("_sched_waveform_s %s+%d value=%s len=%d after=%s reject=%s", + istr(e_path(s->enode)), offset, fmt_values(values, len * s->size), + fmt_time(after), fmt_time(reject)); + + if (unlikely(active_proc->postponed && (after == 0))) + fatal("postponed process %s cannot cause a delta cycle", + istr(e_path(active_proc->source))); + #if 0 const int32_t *nids = _nids; @@ -584,10 +620,6 @@ void _sched_waveform(void *_nids, void *values, int32_t n, fmt_values(values, n * groups[netdb_lookup(netdb, nids[0])].size), n, fmt_time(after), fmt_time(reject)); - if (unlikely(active_proc->postponed && (after == 0))) - fatal("postponed process %s cannot cause a delta cycle", - istr(tree_ident(active_proc->source))); - const uint8_t *vp = values; int offset = 0; while (offset < n) { @@ -763,6 +795,17 @@ void _init_nexus(uint32_t nid, const uint8_t *values) fmt_values(values, n->size * n->width)); memcpy(n->resolved, values, n->size * n->width); + + // Assign the initial value of the drivers + for (unsigned i = 0; i < n->n_drivers; i++) { + waveform_t *dummy = rt_alloc(waveform_stack); + dummy->when = 0; + dummy->next = NULL; + dummy->values = rt_alloc_value(n); + memcpy(dummy->values->data, values, n->size * n->width); + + n->drivers[i].waveforms = dummy; + } } DLLEXPORT @@ -1552,13 +1595,13 @@ static void deltaq_insert_proc(uint64_t delta, rt_proc_t *wake) deltaq_insert(e); } -static void deltaq_insert_driver(uint64_t delta, netgroup_t *group, +static void deltaq_insert_driver(uint64_t delta, rt_nexus_t *nexus, rt_proc_t *driver) { event_t *e = rt_alloc(event_stack); e->when = now + delta; e->kind = EVENT_DRIVER; - e->group = group; + e->nexus = nexus; e->proc = driver; e->wakeup_gen = UINT32_MAX; @@ -1573,7 +1616,7 @@ static void deltaq_walk(uint64_t key, void *user, void *context) fprintf(stderr, "%s\t", fmt_time(e->when)); switch (e->kind) { case EVENT_DRIVER: - fprintf(stderr, "driver\t %s\n", fmt_group(e->group)); + fprintf(stderr, "driver\t %s\n", fmt_nexus(e->nexus)); break; case EVENT_PROCESS: fprintf(stderr, "process\t %s%s\n", istr(e_path(e->proc->source)), @@ -1588,7 +1631,7 @@ static void deltaq_walk(uint64_t key, void *user, void *context) static void deltaq_dump(void) { for (event_t *e = delta_driver; e != NULL; e = e->delta_chain) - fprintf(stderr, "delta\tdriver\t %s\n", fmt_group(e->group)); + fprintf(stderr, "delta\tdriver\t %s\n", istr(e_ident(e->nexus->enode))); for (event_t *e = delta_proc; e != NULL; e = e->delta_chain) fprintf(stderr, "delta\tprocess\t %s%s\n", @@ -1687,27 +1730,27 @@ static void rt_global_event(rt_event_t kind) } } -static value_t *rt_alloc_value(netgroup_t *g) +static value_t *rt_alloc_value(rt_nexus_t *n) { - if (g->free_values == NULL) { - const size_t size = MAX(sizeof(uint64_t), g->size * g->length); + if (n->free_values == NULL) { + const size_t size = MAX(sizeof(uint64_t), n->size * n->width); value_t *v = xmalloc(sizeof(struct value) + size); v->next = NULL; return v; } else { - value_t *v = g->free_values; - g->free_values = v->next; + value_t *v = n->free_values; + n->free_values = v->next; v->next = NULL; return v; } } -static void rt_free_value(netgroup_t *g, value_t *v) +static void rt_free_value(rt_nexus_t *n, value_t *v) { RT_ASSERT(v->next == NULL); - v->next = g->free_values; - g->free_values = v; + v->next = n->free_values; + n->free_values = v; } static void *rt_tmp_alloc(size_t sz) @@ -1822,6 +1865,12 @@ static void rt_setup_scopes_recur(e_node_t e, unsigned *next_scope, r->pending = false; r->usage = 0; r->context = context; + + assert(e_nexuses(p) == 1); + assert(e_procs(e_nexus(p, 0)) == 1); + rt_nexus_t *n = &(nexus[e_pos(e_nexus(p, 0))]); + assert(n->n_drivers == 1); + n->drivers[0].proc = r; } for (int i = 0; i < nsignals; i++) { @@ -1829,12 +1878,15 @@ static void rt_setup_scopes_recur(e_node_t e, unsigned *next_scope, const uint32_t sig_id = (*next_signal)++; rt_signal_t *r = &(signals[sig_id]); - r->enode = s; - r->width = e_width(s); - r->size = e_size(s); + r->enode = s; + r->width = e_width(s); + r->size = e_size(s); + r->n_nexus = e_nexuses(s); + r->nexus = xmalloc_array(r->n_nexus, sizeof(rt_nexus_t*)); - assert(e_nexuses(s) == 1); + assert(r->n_nexus == 1); rt_nexus_t *n = &(nexus[e_pos(e_nexus(s, 0))]); + r->nexus[0] = n; context->signals[i].sig_id = sig_id; context->signals[i].displaced = n->resolved; @@ -1999,65 +2051,66 @@ static void rt_call_module_reset(ident_t name) global_tmp_alloc = _tmp_alloc; } -static int32_t rt_resolve_group(netgroup_t *group, int driver, void *values) +static int32_t rt_resolve_nexus(rt_nexus_t *nexus, int driver, void *values) { // Set driver to -1 for initial call to resolution function - const size_t valuesz = group->size * group->length; + const size_t valuesz = nexus->size * nexus->width; void *resolved = NULL; - if (unlikely(group->flags & NET_F_FORCED)) { - resolved = group->forcing->data; + if (unlikely(nexus->flags & NET_F_FORCED)) { + resolved = nexus->forcing->data; } - else if (group->resolution == NULL) { + else if (nexus->resolution == NULL) { resolved = values; } - else if ((group->resolution->flags & R_IDENT) && (group->n_drivers == 1)) { + else if ((nexus->resolution->flags & R_IDENT) && (nexus->n_drivers == 1)) { // Resolution function behaves like identity for a single driver resolved = values; } - else if ((group->resolution->flags & R_MEMO) && (group->n_drivers == 1)) { + else if ((nexus->resolution->flags & R_MEMO) && (nexus->n_drivers == 1)) { // Resolution function has been memoised so do a table lookup resolved = alloca(valuesz); - for (int j = 0; j < group->length; j++) { + for (int j = 0; j < nexus->width; j++) { const int index = { ((const char *)values)[j] }; - const int8_t r = group->resolution->tab1[index]; + const int8_t r = nexus->resolution->tab1[index]; ((int8_t *)resolved)[j] = r; } } - else if ((group->resolution->flags & R_MEMO) && (group->n_drivers == 2)) { + else if ((nexus->resolution->flags & R_MEMO) && (nexus->n_drivers == 2)) { // Resolution function has been memoised so do a table lookup resolved = alloca(valuesz); - const char *p0 = group->drivers[0].waveforms->values->data; - const char *p1 = group->drivers[1].waveforms->values->data; + const char *p0 = nexus->drivers[0].waveforms->values->data; + const char *p1 = nexus->drivers[1].waveforms->values->data; - for (int j = 0; j < group->length; j++) { + for (int j = 0; j < nexus->width; j++) { int driving[2] = { p0[j], p1[j] }; if (likely(driver >= 0)) driving[driver] = ((const char *)values)[j]; - const int8_t r = group->resolution->tab2[driving[0]][driving[1]]; + const int8_t r = nexus->resolution->tab2[driving[0]][driving[1]]; ((int8_t *)resolved)[j] = r; } } - else if (group->resolution->flags & R_RECORD) { + else if (nexus->resolution->flags & R_RECORD) { // Call resolution function for resolved record - netid_t first = group->first, last = group->first + group->length - 1; +#if 0 + netid_t first = nexus->first, last = nexus->first + nexus->length - 1; for (const netgroup_t *it = group; - it->resolution == group->resolution && it->first > 0 + it->resolution == nexus->resolution && it->first > 0 && !(it->flags & NET_F_BOUNDARY); it = &(groups[netdb_lookup(netdb, it->first - 1)]), first = it->first) ; for (const netgroup_t *it = group; - it->resolution == group->resolution + it->resolution == nexus->resolution && it->first + it->length < netdb_size(netdb) && (it == group || !(it->flags & (NET_F_BOUNDARY | NET_F_OWNS_MEM))); @@ -2069,14 +2122,14 @@ static int32_t rt_resolve_group(netgroup_t *group, int driver, void *values) for (int offset = first; offset <= last;) { netgroup_t *g = &(groups[netdb_lookup(netdb, offset)]); size += g->size * g->length; - if (offset < group->first) + if (offset < nexus->first) group_off = size; - assert(g->n_drivers == group->n_drivers); + assert(g->n_drivers == nexus->n_drivers); offset += g->length; } - uint8_t *inputs = alloca(size * group->n_drivers); + uint8_t *inputs = alloca(size * nexus->n_drivers); size_t ptr = 0; for (int offset = first; offset <= last;) { @@ -2098,23 +2151,24 @@ static int32_t rt_resolve_group(netgroup_t *group, int driver, void *values) } struct uarray u = { - inputs, { { group->resolution->ileft, - group->resolution->ileft + group->n_drivers - 1, + inputs, { { nexus->resolution->ileft, + nexus->resolution->ileft + nexus->n_drivers - 1, RANGE_TO } } }; - uint8_t *result = (uint8_t *)(*group->resolution->fn)(&u); + uint8_t *result = (uint8_t *)(*nexus->resolution->fn)(&u); resolved = result + group_off; +#endif } else { // Must actually call resolution function in general case resolved = alloca(valuesz); - for (int j = 0; j < group->length; j++) { + for (int j = 0; j < nexus->width; j++) { #define CALL_RESOLUTION_FN(type) do { \ - type vals[group->n_drivers]; \ - for (int i = 0; i < group->n_drivers; i++) { \ - const value_t *v = group->drivers[i].waveforms->values; \ + type vals[nexus->n_drivers]; \ + for (int i = 0; i < nexus->n_drivers; i++) { \ + const value_t *v = nexus->drivers[i].waveforms->values; \ vals[i] = ((const type *)v->data)[j]; \ } \ if (likely(driver >= 0)) \ @@ -2122,43 +2176,45 @@ static int32_t rt_resolve_group(netgroup_t *group, int driver, void *values) type *r = (type *)resolved; \ struct uarray u = { \ vals, { \ - { group->resolution->ileft, \ - group->resolution->ileft + group->n_drivers - 1, \ + { nexus->resolution->ileft, \ + nexus->resolution->ileft + nexus->n_drivers - 1, \ RANGE_TO } } \ }; \ - r[j] = (*group->resolution->fn)(&u); \ + r[j] = (*nexus->resolution->fn)(&u); \ } while (0) - FOR_ALL_SIZES(group->size, CALL_RESOLUTION_FN); + FOR_ALL_SIZES(nexus->size, CALL_RESOLUTION_FN); } } int32_t new_flags = NET_F_ACTIVE; - if (memcmp(group->resolved, resolved, valuesz) != 0) + if (memcmp(nexus->resolved, resolved, valuesz) != 0) new_flags |= NET_F_EVENT; // LAST_VALUE is the same as the initial value when // there have been no events on the signal otherwise // only update it when there is an event if (new_flags & NET_F_EVENT) { - if (group->flags & NET_F_LAST_VALUE) - memcpy(group->last_value, group->resolved, valuesz); - memcpy(group->resolved, resolved, valuesz); + //if (nexus->flags & NET_F_LAST_VALUE) + // memcpy(nexus->last_value, nexus->resolved, valuesz); + memcpy(nexus->resolved, resolved, valuesz); - group->last_event = now; + nexus->last_event = now; } return new_flags; } +#if 0 static void rt_group_inital(groupid_t gid, netid_t first, unsigned length) { netgroup_t *g = &(groups[gid]); if ((g->n_drivers == 1) && (g->resolution == NULL)) - rt_resolve_group(g, -1, g->drivers[0].waveforms->values->data); + rt_resolve_nexus(g, -1, g->drivers[0].waveforms->values->data); else if (g->n_drivers > 0) - rt_resolve_group(g, -1, g->resolved); + rt_resolve_nexus(g, -1, g->resolved); } +#endif static void rt_initial(e_node_t top) { @@ -2242,27 +2298,27 @@ static void rt_wakeup(sens_list_t *sl) rt_free(sens_list_stack, sl); } -static bool rt_sched_driver(netgroup_t *group, uint64_t after, +static bool rt_sched_driver(rt_nexus_t *nexus, uint64_t after, uint64_t reject, value_t *values) { if (unlikely(reject > after)) fatal("signal %s pulse reject limit %s is greater than " - "delay %s", fmt_group(group), fmt_time(reject), fmt_time(after)); + "delay %s", fmt_nexus(nexus), fmt_time(reject), fmt_time(after)); int driver = 0; - if (unlikely(group->n_drivers != 1)) { + if (unlikely(nexus->n_drivers != 1)) { // Try to find this process in the list of existing drivers - for (driver = 0; driver < group->n_drivers; driver++) { - if (likely(group->drivers[driver].proc == active_proc)) + for (driver = 0; driver < nexus->n_drivers; driver++) { + if (likely(nexus->drivers[driver].proc == active_proc)) break; } - RT_ASSERT(driver != group->n_drivers); + RT_ASSERT(driver != nexus->n_drivers); } - driver_t *d = &(group->drivers[driver]); + driver_t *d = &(nexus->drivers[driver]); - const size_t valuesz = group->size * group->length; + const size_t valuesz = nexus->size * nexus->width; waveform_t *w = rt_alloc(waveform_stack); w->when = now + after; @@ -2279,7 +2335,7 @@ static bool rt_sched_driver(netgroup_t *group, uint64_t after, && (memcmp(it->values->data, w->values->data, valuesz) != 0)) { waveform_t *next = it->next; last->next = next; - rt_free_value(group, it->values); + rt_free_value(nexus, it->values); rt_free(waveform_stack, it); it = next; } @@ -2297,7 +2353,7 @@ static bool rt_sched_driver(netgroup_t *group, uint64_t after, // up for the empty event bool already_scheduled = false; while (it != NULL) { - rt_free_value(group, it->values); + rt_free_value(nexus, it->values); if (it->when == w->when) already_scheduled = true; @@ -2310,41 +2366,45 @@ static bool rt_sched_driver(netgroup_t *group, uint64_t after, return already_scheduled; } -static void rt_update_group(netgroup_t *group, int driver, void *values) +static void rt_update_nexus(rt_nexus_t *nexus, int driver, void *values) { - const size_t valuesz = group->size * group->length; + const size_t valuesz = nexus->size * nexus->width; - TRACE("update group %s values=%s driver=%d", - fmt_group(group), fmt_values(values, valuesz), driver); + TRACE("update nexus %s values=%s driver=%d", + fmt_nexus(nexus), fmt_values(values, valuesz), driver); - const int32_t new_flags = rt_resolve_group(group, driver, values); - group->flags |= new_flags; + const int32_t new_flags = rt_resolve_nexus(nexus, driver, values); + nexus->flags |= new_flags; - if (unlikely(n_active_groups == n_active_alloc)) { + if (unlikely(n_active_nexus == n_active_alloc)) { n_active_alloc *= 2; const size_t newsz = n_active_alloc * sizeof(struct netgroup *); - active_groups = xrealloc(active_groups, newsz); + active_nexus = xrealloc(active_nexus, newsz); } - active_groups[n_active_groups++] = group; + active_nexus[n_active_nexus++] = nexus; - // Wake up any processes sensitive to this group + // Wake up any processes sensitive to this nexus if (new_flags & NET_F_EVENT) { sens_list_t *it, *last = NULL, *next = NULL; - // First wakeup everything on the group specific pending list - for (it = group->pending; it != NULL; it = next) { + (void)next; + (void)last; + + // First wakeup everything on the nexus specific pending list + for (it = nexus->pending; it != NULL; it = next) { next = it->next; rt_wakeup(it); - group->pending = next; + nexus->pending = next; } // Now check the global pending list - if (group->flags & NET_F_GLOBAL) { + if (nexus->flags & NET_F_GLOBAL) { +#if 0 for (it = pending; it != NULL; it = next) { next = it->next; - const netid_t x = group->first; - const netid_t y = group->first + group->length - 1; + const netid_t x = nexus->first; + const netid_t y = nexus->first + nexus->length - 1; const netid_t a = it->first; const netid_t b = it->last; @@ -2360,10 +2420,11 @@ static void rt_update_group(netgroup_t *group, int driver, void *values) else last = it; } +#endif } // Schedule any callbacks to run - for (watch_list_t *wl = group->watching; wl != NULL; wl = wl->next) { + for (watch_list_t *wl = nexus->watching; wl != NULL; wl = wl->next) { if (!wl->watch->pending) { wl->watch->chain_pending = callbacks; wl->watch->pending = true; @@ -2373,31 +2434,31 @@ static void rt_update_group(netgroup_t *group, int driver, void *values) } } -static void rt_update_driver(netgroup_t *group, rt_proc_t *proc) +static void rt_update_driver(rt_nexus_t *nexus, rt_proc_t *proc) { if (likely(proc != NULL)) { // Find the driver owned by proc int driver; - for (driver = 0; driver < group->n_drivers; driver++) { - if (likely(group->drivers[driver].proc == proc)) + for (driver = 0; driver < nexus->n_drivers; driver++) { + if (likely(nexus->drivers[driver].proc == proc)) break; } - RT_ASSERT(driver != group->n_drivers); + RT_ASSERT(driver != nexus->n_drivers); - waveform_t *w_now = group->drivers[driver].waveforms; + waveform_t *w_now = nexus->drivers[driver].waveforms; waveform_t *w_next = w_now->next; if (likely((w_next != NULL) && (w_next->when == now))) { - rt_update_group(group, driver, w_next->values->data); - group->drivers[driver].waveforms = w_next; - rt_free_value(group, w_now->values); + rt_update_nexus(nexus, driver, w_next->values->data); + nexus->drivers[driver].waveforms = w_next; + rt_free_value(nexus, w_now->values); rt_free(waveform_stack, w_now); } else RT_ASSERT(w_now != NULL); } - else if (group->flags & NET_F_FORCED) - rt_update_group(group, -1, group->forcing->data); + else if (nexus->flags & NET_F_FORCED) + rt_update_nexus(nexus, -1, nexus->forcing->data); } static bool rt_stale_event(event_t *e) @@ -2569,7 +2630,7 @@ static void rt_cycle(int stop_delta) rt_run(event->proc, false /* reset */); break; case EVENT_DRIVER: - rt_update_driver(event->group, event->proc); + rt_update_driver(event->nexus, event->proc); break; case EVENT_TIMEOUT: (*event->timeout_fn)(now, event->timeout_user); @@ -2591,11 +2652,11 @@ static void rt_cycle(int stop_delta) rt_resume_processes(&resume); rt_global_event(RT_END_OF_PROCESSES); - for (unsigned i = 0; i < n_active_groups; i++) { - netgroup_t *g = active_groups[i]; - g->flags &= ~(NET_F_ACTIVE | NET_F_EVENT); + for (unsigned i = 0; i < n_active_nexus; i++) { + rt_nexus_t *n = active_nexus[i]; + n->flags &= ~(NET_F_ACTIVE | NET_F_EVENT); } - n_active_groups = 0; + n_active_nexus = 0; if (!rt_next_cycle_is_delta()) { can_create_delta = false; @@ -2620,44 +2681,39 @@ static tree_t rt_recall_decl(const char *name) fatal("cannot find name %s in elaborated design", name); } -static void rt_cleanup_group(groupid_t gid, netid_t first, unsigned length) +static void rt_cleanup_nexus(rt_nexus_t *n) { - netgroup_t *g = &(groups[gid]); - - RT_ASSERT(g->first == first); - RT_ASSERT(g->length == length); - - if (g->flags & NET_F_OWNS_MEM) - free(g->resolved); + if (n->flags & NET_F_OWNS_MEM) + free(n->resolved); - free(g->forcing); + free(n->forcing); - for (int j = 0; j < g->n_drivers; j++) { - while (g->drivers[j].waveforms != NULL) { - waveform_t *next = g->drivers[j].waveforms->next; - rt_free_value(g, g->drivers[j].waveforms->values); - rt_free(waveform_stack, g->drivers[j].waveforms); - g->drivers[j].waveforms = next; + for (int j = 0; j < n->n_drivers; j++) { + while (n->drivers[j].waveforms != NULL) { + waveform_t *next = n->drivers[j].waveforms->next; + rt_free_value(n, n->drivers[j].waveforms->values); + rt_free(waveform_stack, n->drivers[j].waveforms); + n->drivers[j].waveforms = next; } } - free(g->drivers); + free(n->drivers); - while (g->free_values != NULL) { - value_t *next = g->free_values->next; - free(g->free_values); - g->free_values = next; + while (n->free_values != NULL) { + value_t *next = n->free_values->next; + free(n->free_values); + n->free_values = next; } - while (g->pending != NULL) { - sens_list_t *next = g->pending->next; - rt_free(sens_list_stack, g->pending); - g->pending = next; + while (n->pending != NULL) { + sens_list_t *next = n->pending->next; + rt_free(sens_list_stack, n->pending); + n->pending = next; } - while (g->watching != NULL) { - watch_list_t *next = g->watching->next; - free(g->watching); - g->watching = next; + while (n->watching != NULL) { + watch_list_t *next = n->watching->next; + free(n->watching); + n->watching = next; } } @@ -2677,6 +2733,9 @@ static void rt_cleanup(e_node_t top) //netdb_walk(netdb, rt_cleanup_group); //netdb_close(netdb); + for (unsigned i = 0; i < n_nexus; i++) + rt_cleanup_nexus(&(nexus[i])); + free(nexus); nexus = NULL; @@ -2849,7 +2908,7 @@ void rt_start_of_tool(e_node_t top) callback_stack = rt_alloc_stack_new(sizeof(callback_t), "callback"); n_active_alloc = 128; - active_groups = xmalloc(n_active_alloc * sizeof(struct netgroup *)); + active_nexus = xmalloc(n_active_alloc * sizeof(struct netgroup *)); global_tmp_stack = mmap_guarded(GLOBAL_TMP_STACK_SZ, "global temp stack"); proc_tmp_stack = mmap_guarded(PROC_TMP_STACK_SZ, "process temp stack"); @@ -2916,7 +2975,7 @@ void rt_set_timeout_cb(uint64_t when, timeout_fn_t fn, void *user) event_t *e = rt_alloc(event_stack); e->when = now + when; e->kind = EVENT_TIMEOUT; - e->group = NULL; + e->nexus = NULL; e->proc = NULL; e->timeout_fn = fn; e->timeout_user = user; @@ -3000,20 +3059,20 @@ size_t rt_watch_value(watch_t *w, uint64_t *buf, size_t max, bool last) return offset; } -static size_t rt_group_string(netgroup_t *group, const char *map, +static size_t rt_nexus_string(rt_nexus_t *nexus, const char *map, char *buf, const char *end1) { char *bp = buf; - const char *vals = group->resolved; + const char *vals = nexus->resolved; if (likely(map != NULL)) { - for (int j = 0; j < group->length; j++) { + for (int j = 0; j < nexus->width; j++) { if (bp + 1 < end1) *bp++ = map[(int)vals[j]]; } } else { - for (int j = 0; j < group->length; j++) { + for (int j = 0; j < nexus->width; j++) { if (bp + 1 < end1) *bp++ = vals[j]; } @@ -3027,19 +3086,24 @@ static size_t rt_group_string(netgroup_t *group, const char *map, size_t rt_watch_string(watch_t *w, const char *map, char *buf, size_t max) { +#if 0 char *bp = buf; size_t offset = 0; for (int i = 0; i < w->n_groups; i++) { netgroup_t *g = w->groups[i]; - bp += rt_group_string(g, map, bp, buf + max); + bp += rt_nexus_string(g, map, bp, buf + max); offset += g->length; } return offset + 1; +#else + return 0; +#endif } size_t rt_signal_string(tree_t s, const char *map, char *buf, size_t max) { +#if 0 char *bp = buf; const int nnets = tree_nets(s); int offset = 0; @@ -3051,6 +3115,9 @@ size_t rt_signal_string(tree_t s, const char *map, char *buf, size_t max) } return offset + 1; +#else + return 0; +#endif } size_t rt_signal_value(tree_t s, uint64_t *buf, size_t max) -- 2.39.2