From 8b4dc05ff8b326a40905334095bfa682fb2c0d94 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 12 Feb 2013 19:34:31 -0800 Subject: [PATCH] vlog95: for a part/pv look for the strength at the driver A part/pv passes strength information so we need to use the real driver to get the appropriate drive information. --- tgt-vlog95/expr.c | 1 - tgt-vlog95/logic_lpm.c | 47 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index c9615fe5e..32b3001fb 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -190,7 +190,6 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) emit_expr(scope, ivl_expr_oper2(expr), wid); fprintf(vlog_out, "))"); break; - break; default: emit_expr(scope, ivl_expr_oper1(expr), wid); fprintf(vlog_out, ""); diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index f90e99fad..34d8cb78f 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -108,10 +108,53 @@ static void emit_gate_strength(ivl_net_logic_t nlogic, unsigned strength_type) "gate", ivl_logic_file(nlogic), ivl_logic_lineno(nlogic)); } +/* + * Look for a single driver behind an LPM that passes strength information + * and get the real drive information from it. + */ +static void get_unique_lpm_drive(ivl_lpm_t lpm, ivl_drive_t *drive1, + ivl_drive_t *drive0) +{ + ivl_nexus_t nex = ivl_lpm_data(lpm, 0); + unsigned idx, count = ivl_nexus_ptrs(nex); + unsigned have_driver = 0; + + for (idx = 0; idx < count; idx += 1) { + ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); + ivl_drive_t cur_drive1 = ivl_nexus_ptr_drive1(nex_ptr); + ivl_drive_t cur_drive0 = ivl_nexus_ptr_drive0(nex_ptr); + if ((cur_drive1 == IVL_DR_HiZ) && + (cur_drive0 == IVL_DR_HiZ)) continue; + assert(! have_driver); + *drive1 = cur_drive1; + *drive0 = cur_drive0; + have_driver = 1; + } + + /* This should never happen. */ + if (! have_driver) { + fprintf(stderr, "%s:%u: vlog95 error: Unable to find drive " + "information for strength transparent LPM.\n", + ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); + vlog_errors += 1; + } +} + static void emit_lpm_strength(ivl_lpm_t lpm) { - emit_strength(ivl_lpm_drive1(lpm), ivl_lpm_drive0(lpm), 2, - "LPM", ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); + ivl_lpm_type_t type = ivl_lpm_type(lpm); + ivl_drive_t drive1 = IVL_DR_STRONG; + ivl_drive_t drive0 = IVL_DR_STRONG; + /* This LPM object passes strength information so we need to look + * for the strength information at the real driver. */ + if (type == IVL_LPM_PART_PV) { + get_unique_lpm_drive(lpm, &drive1, &drive0); + } else { + drive1 = ivl_lpm_drive1(lpm); + drive0 = ivl_lpm_drive0(lpm); + } + emit_strength(drive1, drive0, 2, "LPM", + ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); } static void emit_delay(ivl_scope_t scope, ivl_expr_t rise, ivl_expr_t fall,