diff --git a/vvp/island_tran.cc b/vvp/island_tran.cc index 17240dc78..ae51b41f5 100644 --- a/vvp/island_tran.cc +++ b/vvp/island_tran.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2018 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -45,14 +45,14 @@ struct vvp_island_branch_tran : public vvp_island_branch { vvp_island_branch_tran(vvp_net_t*en__, bool active_high__, unsigned width__, unsigned part__, - unsigned offset__); + unsigned offset__, bool resistive__); bool run_test_enabled(); void run_resolution(); void run_output(); vvp_net_t*en; unsigned width, part, offset; - bool active_high; + bool active_high, resistive; tran_state_t state; }; @@ -60,9 +60,10 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__, bool active_high__, unsigned width__, unsigned part__, - unsigned offset__) + unsigned offset__, + bool resistive__) : en(en__), width(width__), part(part__), offset(offset__), - active_high(active_high__) + active_high(active_high__), resistive(resistive__) { state = en__ ? tran_disabled : tran_enabled; } @@ -235,7 +236,8 @@ bool vvp_island_branch_tran::run_test_enabled() // input is 'x' or 'z'. We use the rules that are given for MOS switches. inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a, const vvp_vector8_t&b, - tran_state_t state) + tran_state_t state, + unsigned str_map[8]) { assert(a.size() == b.size()); vvp_vector8_t out (a.size()); @@ -243,6 +245,9 @@ inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a, for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { vvp_scalar_t a_bit = a.value(idx); vvp_scalar_t b_bit = b.value(idx); + b_bit = vvp_scalar_t(b_bit.value(), + str_map[b_bit.strength0()], + str_map[b_bit.strength1()]); if (state == tran_unknown) { switch (b_bit.value()) { case BIT4_0: @@ -293,8 +298,8 @@ static void push_value_through_branch(const vvp_vector8_t&val, // previously collected (and resolved) for the port. if (branch->width == 0) { // There are no part selects. - dst_port->value = resolve_ambiguous(dst_port->value, val, - branch->state); + dst_port->value = resolve_ambiguous(dst_port->value, val, branch->state, + vvp_switch_strength_map[branch->resistive]); } else if (dst_ab == 1) { // The other side is a strict subset (part select) @@ -413,7 +418,7 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe) vvp_island_branch_tran*br = new vvp_island_branch_tran(en, sense ? true : false, - 0, 0, 0); + 0, 0, 0, false); use_island->add_branch(br, pa, pb); @@ -430,7 +435,7 @@ void compile_island_tranvp(char*island, char*pa, char*pb, free(island); vvp_island_branch_tran*br = new vvp_island_branch_tran(NULL, false, - wid, par, off); + wid, par, off, false); use_island->add_branch(br, pa, pb); diff --git a/vvp/npmos.cc b/vvp/npmos.cc index 1359c9691..1eae2bc07 100644 --- a/vvp/npmos.cc +++ b/vvp/npmos.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2005-2018 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -19,9 +19,10 @@ # include "npmos.h" -vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert) +vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert, bool resistive) { inv_en_ = enable_invert; + resistive_ = resistive; } @@ -58,12 +59,18 @@ void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr) { + const unsigned*strength_map = vvp_switch_strength_map[resistive_]; + vvp_vector8_t out (bit_.size()); for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { vvp_bit4_t b_en = en_.value(idx); vvp_scalar_t b_bit = bit_.value(idx); + b_bit = vvp_scalar_t(b_bit.value(), + strength_map[b_bit.strength0()], + strength_map[b_bit.strength1()]); + switch (b_en) { case BIT4_0: out.set_bit(idx, b_bit); @@ -93,7 +100,7 @@ void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr) vvp_fun_pmos::vvp_fun_pmos(bool enable_invert) -: vvp_fun_pmos_(enable_invert) +: vvp_fun_pmos_(enable_invert, false) { } @@ -112,7 +119,7 @@ void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) } vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert) -: vvp_fun_pmos_(enable_invert) +: vvp_fun_pmos_(enable_invert, true) { } @@ -126,7 +133,7 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) if (ptr.port() != 0) return; - bit_ = resistive_reduction(bit); + bit_ = bit; generate_output_(ptr); } @@ -135,8 +142,9 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) * CMOS primitive. */ -vvp_fun_cmos_::vvp_fun_cmos_() +vvp_fun_cmos_::vvp_fun_cmos_(bool resistive) { + resistive_ = resistive; } void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit, @@ -175,6 +183,8 @@ void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) { + const unsigned*strength_map = vvp_switch_strength_map[resistive_]; + vvp_vector8_t out (bit_.size()); for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { @@ -182,6 +192,10 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) vvp_bit4_t b_p_en = p_en_.value(idx); vvp_scalar_t b_bit = bit_.value(idx); + b_bit = vvp_scalar_t(b_bit.value(), + strength_map[b_bit.strength0()], + strength_map[b_bit.strength1()]); + if (b_n_en == BIT4_1 || b_p_en == BIT4_0) { out.set_bit(idx, b_bit); } else if (b_n_en == BIT4_0 && b_p_en == BIT4_1) { @@ -206,7 +220,7 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) } vvp_fun_cmos::vvp_fun_cmos() -: vvp_fun_cmos_() +: vvp_fun_cmos_(false) { } @@ -225,7 +239,7 @@ void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) } vvp_fun_rcmos::vvp_fun_rcmos() -: vvp_fun_cmos_() +: vvp_fun_cmos_(true) { } @@ -239,6 +253,6 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) if (ptr.port() != 0) return; - bit_ = resistive_reduction(bit); + bit_ = bit; generate_output_(ptr); } diff --git a/vvp/npmos.h b/vvp/npmos.h index cb6950685..9a91ca49d 100644 --- a/vvp/npmos.h +++ b/vvp/npmos.h @@ -1,7 +1,7 @@ #ifndef IVL_npmos_H #define IVL_npmos_H /* - * Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2005-2018 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -46,7 +46,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t { public: - explicit vvp_fun_pmos_(bool enable_invert); + explicit vvp_fun_pmos_(bool enable_invert, bool resistive); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_context_t); @@ -62,7 +62,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t { vvp_vector8_t bit_; vvp_vector4_t en_; - bool inv_en_; + bool inv_en_, resistive_; }; class vvp_fun_pmos : public vvp_fun_pmos_ { @@ -109,7 +109,7 @@ class vvp_fun_rpmos : public vvp_fun_pmos_ { class vvp_fun_cmos_ : public vvp_net_fun_t { public: - explicit vvp_fun_cmos_(); + explicit vvp_fun_cmos_(bool resistive); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit, vvp_context_t); @@ -126,6 +126,7 @@ class vvp_fun_cmos_ : public vvp_net_fun_t { vvp_vector8_t bit_; vvp_vector4_t n_en_; vvp_vector4_t p_en_; + bool resistive_; }; class vvp_fun_cmos : public vvp_fun_cmos_ { diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 4b53978fa..73852fcba 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -3686,31 +3686,28 @@ vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b) return res; } -vvp_vector8_t resistive_reduction(const vvp_vector8_t&that) -{ - static unsigned rstr[8] = { - 0, /* Hi-Z --> Hi-Z */ - 1, /* Small capacitance --> Small capacitance */ - 1, /* Medium capacitance --> Small capacitance */ - 2, /* Weak drive --> Medium capacitance */ - 2, /* Large capacitance --> Medium capacitance */ - 3, /* Pull drive --> Weak drive */ - 5, /* Strong drive --> Pull drive */ - 5 /* Supply drive --> Pull drive */ - }; - - vvp_vector8_t res (that.size()); - - for (unsigned idx = 0 ; idx < res.size() ; idx += 1) { - vvp_scalar_t bit = that.value(idx); - bit = vvp_scalar_t(bit.value(), - rstr[bit.strength0()], - rstr[bit.strength1()]); - res.set_bit(idx, bit); +unsigned vvp_switch_strength_map[2][8] = { + { // non-resistive + 0, /* High impedance --> High impedance */ + 1, /* Small capacitor --> Small capacitor */ + 2, /* Medium capacitor --> Medium capacitor */ + 3, /* Weak drive --> Weak drive */ + 4, /* Large capacitor --> Large capacitor */ + 5, /* Pull drive --> Pull drive */ + 6, /* Strong drive --> Strong drive */ + 6 /* Supply drive --> Strong drive */ + }, + { // resistive + 0, /* High impedance --> High impedance */ + 1, /* Small capacitor --> Small capacitor */ + 1, /* Medium capacitor --> Small capacitor */ + 2, /* Weak drive --> Medium capacitor */ + 2, /* Large capacitor --> Medium capacitor */ + 3, /* Pull drive --> Weak drive */ + 5, /* Strong drive --> Pull drive */ + 5 /* Supply drive --> Pull drive */ } - - return res; -} +}; vvp_vector4_t reduce4(const vvp_vector8_t&that) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index b5bf544c1..c143fa571 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1,7 +1,7 @@ #ifndef IVL_vvp_net_H #define IVL_vvp_net_H /* - * Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2018 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -954,9 +954,11 @@ inline vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b) return out; } - /* This function implements the strength reduction implied by - Verilog standard resistive devices. */ -extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a); + /* This lookup tabke implements the strength reduction implied by + Verilog standard switch devices. The major dimension selects + between non-resistive and resistive devices. */ +extern unsigned vvp_switch_strength_map[2][8]; + /* The reduce4 function converts a vector8 to a vector4, losing strength information in the process. */ extern vvp_vector4_t reduce4(const vvp_vector8_t&that);