diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index a08ee3792..a633df717 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -665,6 +665,125 @@ static int emit_tf_process(ivl_scope_t scope, ivl_scope_t parent) return 0; } +static void emit_path_delay(ivl_scope_t scope, ivl_delaypath_t dpath) +{ + unsigned idx, count = 6; + uint64_t pdlys [12]; + pdlys[0] = ivl_path_delay(dpath, IVL_PE_01); + pdlys[1] = ivl_path_delay(dpath, IVL_PE_10); + pdlys[2] = ivl_path_delay(dpath, IVL_PE_0z); + pdlys[3] = ivl_path_delay(dpath, IVL_PE_z1); + pdlys[4] = ivl_path_delay(dpath, IVL_PE_1z); + pdlys[5] = ivl_path_delay(dpath, IVL_PE_z0); + pdlys[6] = ivl_path_delay(dpath, IVL_PE_0x); + pdlys[7] = ivl_path_delay(dpath, IVL_PE_x1); + pdlys[8] = ivl_path_delay(dpath, IVL_PE_1x); + pdlys[9] = ivl_path_delay(dpath, IVL_PE_x0); + pdlys[10] = ivl_path_delay(dpath, IVL_PE_xz); + pdlys[11] = ivl_path_delay(dpath, IVL_PE_zx); + /* If the first six pdlys match then this may be a 1 delay form. */ + if ((pdlys[0] == pdlys[1]) && + (pdlys[0] == pdlys[2]) && + (pdlys[0] == pdlys[3]) && + (pdlys[0] == pdlys[4]) && + (pdlys[0] == pdlys[5])) count = 1; + /* Check to see if only a rise and fall value are given for the first + * six pdlys. */ + else if ((pdlys[0] == pdlys[2]) && + (pdlys[0] == pdlys[3]) && + (pdlys[1] == pdlys[4]) && + (pdlys[1] == pdlys[5])) count = 2; + /* Check to see if a rise, fall and high-Z value are given for the + * first six pdlys. */ + else if ((pdlys[0] == pdlys[3]) && + (pdlys[1] == pdlys[5]) && + (pdlys[2] == pdlys[4])) count = 3; + /* Now check to see if the 'bx related pdlys match the reduced + * delay form. If not then this is a twelve delay value. */ + if ((pdlys[6] != ((pdlys[0] < pdlys[2]) ? pdlys[0] : pdlys[2])) || + (pdlys[8] != ((pdlys[1] < pdlys[4]) ? pdlys[1] : pdlys[4])) || + (pdlys[11] != ((pdlys[3] < pdlys[5]) ? pdlys[3] : pdlys[5])) || + (pdlys[7] != ((pdlys[0] > pdlys[3]) ? pdlys[0] : pdlys[3])) || + (pdlys[9] != ((pdlys[1] > pdlys[5]) ? pdlys[1] : pdlys[5])) || + (pdlys[10] != ((pdlys[2] > pdlys[4]) ? pdlys[2] : pdlys[4]))) { + count = 12; + } + emit_scaled_delay(scope, pdlys[0]); + for(idx = 1; idx < count; idx += 1) { + fprintf(vlog_out, ", "); + emit_scaled_delay(scope, pdlys[idx]); + } +} + +static void emit_specify_paths(ivl_scope_t scope, ivl_signal_t sig) +{ + unsigned idx, count = ivl_signal_npath(sig); + for(idx = 0; idx < count; idx += 1) { + ivl_delaypath_t dpath = ivl_signal_path(sig, idx); + ivl_nexus_t cond = ivl_path_condit(dpath); + ivl_nexus_t source = ivl_path_source(dpath); + unsigned has_edge = 0; + fprintf(vlog_out, "%*c", indent, ' '); + if (cond) { + fprintf(vlog_out, "if ("); + emit_nexus_as_ca(scope, cond, 0); + fprintf(vlog_out, ") "); + } else if (ivl_path_is_condit(dpath)) { + fprintf(vlog_out, "ifnone "); + } + fprintf(vlog_out, "("); + if (ivl_path_source_posedge(dpath)) { + fprintf(vlog_out, "posedge "); + has_edge = 1; + } + if (ivl_path_source_negedge(dpath)) { + fprintf(vlog_out, "negedge "); + has_edge = 1; + } + emit_nexus_as_ca(scope, source, 0); + fprintf(vlog_out, " =>"); + /* The compiler does not keep the source expression for an edge + * sensitive path so add a constant to get the syntax right. */ + if (has_edge) { + fprintf(vlog_out, "(%s : 1'bx /* Missing */)", + ivl_signal_basename(sig)); + } else { + fprintf(vlog_out, "%s", ivl_signal_basename(sig)); + } + fprintf(vlog_out, ") = ("); + emit_path_delay(scope, dpath); + fprintf(vlog_out, ");\n"); + } +} + +/* + * The path delay information from the specify block is attached to the + * output ports. + */ +static void emit_specify(ivl_scope_t scope) +{ + unsigned word, idx, count = ivl_scope_ports(scope); + unsigned need_specify = 0; + for (idx = 0; idx < count; idx += 1) { + ivl_nexus_t nex = ivl_scope_mod_port(scope, idx); + ivl_signal_t port = get_port_from_nexus(scope, nex, &word); +// HERE: Do we need to use word? See emit_module_port_def(). + assert(port); + if (ivl_signal_npath(port)) { + if (! need_specify) { + fprintf(vlog_out, "\n%*cspecify\n", indent, ' '); + need_specify = 1; + indent += indent_incr; + } + emit_specify_paths(scope, port); + } + } + if (need_specify) { + indent -= indent_incr; + fprintf(vlog_out, "%*cendspecify\n", indent, ' '); + } +} + /* * This search method may be slow for a large structural design with a * large number of gate types. That's not what this converter was built @@ -852,9 +971,12 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent) emit_stmt(scope, ivl_scope_def(scope)); } - /* Now print out any sub-scopes. */ + /* Print any sub-scopes. */ ivl_scope_children(scope, (ivl_scope_f*) emit_scope, scope); + /* And finally print a specify block when needed. */ + if (sc_type == IVL_SCT_MODULE) emit_specify(scope); + /* Output the scope ending. */ assert(indent >= indent_incr); indent -= indent_incr;