From 6f0d3ae3323f6bf9c8f67462402db7e743a0f9d5 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 19 Mar 2022 14:46:18 +0100 Subject: [PATCH 1/4] ivl_type_s: Add get_scalar() method Currently only the netvector_t type implements the get_scalar() method. To check whether a type is scalar it is first cast to netvector_t and then the method is called. But there are other types, such as areal that can also be scalar. To support indicating that a real type is scalar add a virtual get_scalar() method to ivl_type_s, which is the base class for all types. Signed-off-by: Lars-Peter Clausen --- netlist.cc | 6 ++---- nettypes.cc | 5 +++++ nettypes.h | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/netlist.cc b/netlist.cc index a4b05c413..a96728765 100644 --- a/netlist.cc +++ b/netlist.cc @@ -715,10 +715,8 @@ bool NetNet::get_signed() const bool NetNet::get_scalar() const { - if (const netvector_t*vec = dynamic_cast (net_type_)) - return vec->get_scalar(); - else - return false; + ivl_assert(*this, net_type_); + return net_type_->get_scalar(); } const netenum_t*NetNet::enumeration(void) const diff --git a/nettypes.cc b/nettypes.cc index 23360fcee..d669bd9fe 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -56,6 +56,11 @@ bool ivl_type_s::get_signed() const return false; } +bool ivl_type_s::get_scalar() const +{ + return false; +} + bool ivl_type_s::type_compatible(ivl_type_t that) const { if (this == that) diff --git a/nettypes.h b/nettypes.h index 48ce48fd2..0c26678dc 100644 --- a/nettypes.h +++ b/nettypes.h @@ -45,6 +45,7 @@ class ivl_type_s { // those specific types. virtual ivl_variable_type_t base_type() const; virtual bool get_signed() const; + virtual bool get_scalar() const; // Return true if "that" type is compatible with this // type. Compatible means the types are essentially the same. From 4d0f005a1066d10e6b47eff25966c57acbf0b782 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Jan 2022 18:27:36 +0100 Subject: [PATCH 2/4] netreal_t: Report as signed and scalar reals are both signed and scalar. But the real_type_t currently reports as neither. This isn't much of a problem because most real signals are implemented using netvector_t with the base type set to IVL_VT_REAL, for which the signedness is correctly reported. Function return values and class properties use the netreal_t as their data type, but most places that work with reals check the base type and assume that the value is signed when the base type is real. The only place where this really makes a difference at the moment is the Verilog-AMS function when being passed a function call as its argument. In that case the `abs()` function will be optimized away and a negative value will be passed through as negative. But going forward netreal_t is also going to be used for the data type of real type signals. To fix the `abs()` issue and to be ready to switch real signals over to using netreal_t as their type implement the appropriate methods on netreal_t. Signed-off-by: Lars-Peter Clausen --- netscalar.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netscalar.h b/netscalar.h index ba1ba7975..41506a7ba 100644 --- a/netscalar.h +++ b/netscalar.h @@ -28,6 +28,8 @@ class netreal_t : public ivl_type_s { ~netreal_t(); ivl_variable_type_t base_type() const; + bool get_signed() const { return true; } + bool get_scalar() const { return true; } std::ostream& debug_dump(std::ostream&) const; From 1bf568d808d5cfa26aa10ad019268e1b3f51f132 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 9 Jan 2022 00:27:56 +0100 Subject: [PATCH 3/4] Use `real_type_t` as the data type for `real` type signals Currently a `vector_type_t` with the base type set to `IVL_VT_REAL` is used as the data type for real type signals. But there is also the `real_type_t` data type, which is used as the data type for function return types and class properties. Move signals also over to using `real_type_t`. This ensures consistent behavior between all sorts of constructs with a data type, makes sure that `vector_type_t` is only used for vector types. It also allows to eventually differentiate between `real` and `shortreal` at the elaboration stage. Currently this information is discarded by the parser. Signed-off-by: Lars-Peter Clausen --- elab_sig.cc | 10 ++-------- netlist.cc | 1 + pform.cc | 13 +++++-------- pform_disciplines.cc | 4 +++- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index cca3a4187..83bc2ce5c 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -937,12 +937,7 @@ bool test_ranges_eeq(const vector&lef, const vector&rig) ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope, const std::vector&packed_dimensions) const { - if (dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_)) { + if (set_data_type_ && !dynamic_cast(set_data_type_)) { ivl_type_t use_type = set_data_type_->elaborate_type(des, scope); ivl_assert(*this, packed_dimensions.empty()); return use_type; @@ -962,8 +957,7 @@ ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope, } ivl_assert(*this, use_data_type == IVL_VT_LOGIC || - use_data_type == IVL_VT_BOOL || - use_data_type == IVL_VT_REAL); + use_data_type == IVL_VT_BOOL); netvector_t*vec = new netvector_t(packed_dimensions, use_data_type); vec->set_signed(get_signed()); diff --git a/netlist.cc b/netlist.cc index a96728765..cb2ee73a6 100644 --- a/netlist.cc +++ b/netlist.cc @@ -32,6 +32,7 @@ # include "netdarray.h" # include "netenum.h" # include "netparray.h" +# include "netscalar.h" # include "netqueue.h" # include "netstruct.h" # include "netvector.h" diff --git a/pform.cc b/pform.cc index 0fd56df41..a5b178478 100644 --- a/pform.cc +++ b/pform.cc @@ -2569,7 +2569,6 @@ void pform_module_define_port(const struct vlltype&li, list*attr, bool keep_attr) { - data_type_t*packed_type = 0; ivl_variable_type_t data_type = IVL_VT_NO_TYPE; bool signed_flag = false; @@ -2601,6 +2600,7 @@ void pform_module_define_port(const struct vlltype&li, data_type = vec_type->base_type; signed_flag = vec_type->signed_flag; prange = vec_type->pdims.get(); + vtype = 0; } else if (real_type_t*rtype = dynamic_cast(vtype)) { data_type = IVL_VT_REAL; signed_flag = true; @@ -2614,7 +2614,6 @@ void pform_module_define_port(const struct vlltype&li, } else if (vtype) { if (vtype->figure_packed_base_type() != IVL_VT_NO_TYPE) { data_type = vtype->figure_packed_base_type(); - packed_type = vtype; } else { VLerror(li, "sorry: Given type %s not supported here (%s:%d).", typeid(*vtype).name(), __FILE__, __LINE__); @@ -2631,10 +2630,10 @@ void pform_module_define_port(const struct vlltype&li, cur->set_signed(signed_flag); - if (packed_type) { - cur->set_data_type(packed_type); + if (vtype) + cur->set_data_type(vtype); - } else if (prange == 0) { + if (prange == 0) { cur->set_range_scalar((type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); } else { @@ -2966,8 +2965,7 @@ vector*pform_make_task_ports(const struct vlltype&loc, } if (/*real_type_t*real_type = */ dynamic_cast (vtype)) { - ret = pform_make_task_ports(loc, pt, IVL_VT_REAL, - true, 0, ports); + ret = do_make_task_ports(loc, pt, IVL_VT_REAL, vtype, ports); } if (dynamic_cast (vtype)) { @@ -3442,7 +3440,6 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { - pform_set_net_range(names, 0, true, 0); vt = IVL_VT_REAL; } diff --git a/pform_disciplines.cc b/pform_disciplines.cc index 3e9ce838a..0e3c2e7f7 100644 --- a/pform_disciplines.cc +++ b/pform_disciplines.cc @@ -209,7 +209,9 @@ void pform_attach_discipline(const struct vlltype&loc, error_count += 1; } else { - cur_net->set_data_type(IVL_VT_REAL); + data_type_t *type = new real_type_t(real_type_t::REAL); + FILE_NAME(type, loc); + cur_net->set_data_type(type); cur_net->set_discipline(discipline); } } From 4ae2eec275d8cd1b8475b2be5ae55ce04af37e79 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 12 Apr 2022 18:37:34 +0200 Subject: [PATCH 4/4] Add regression test for Verilog AMS abs() with function call argument Check that the behavior of the Verilog AMS `abs()` function is correct when its argument is a function call. Check this for both vector as well as real types. This test is largely a copy of the existing vams_abs2 test, just replacing the identifier argument with a function call argument. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/vams_abs3.v | 59 +++++++++++++++++++++++++++++++++++++ ivtest/regress-vams.list | 1 + ivtest/regress-vlog95.list | 1 + 3 files changed, 61 insertions(+) create mode 100644 ivtest/ivltests/vams_abs3.v diff --git a/ivtest/ivltests/vams_abs3.v b/ivtest/ivltests/vams_abs3.v new file mode 100644 index 000000000..3111f9df0 --- /dev/null +++ b/ivtest/ivltests/vams_abs3.v @@ -0,0 +1,59 @@ +// Check that VAMS `abs()` functions works if its argument is a function call + +module main; + + function reg signed [7:0] fv(input reg signed [7:0] x); + fv = x; + endfunction + + function real fr(input real x); + fr = x; + endfunction + + reg signed [7:0] a; + wire signed [7:0] vala = abs(fv(a)); + + reg real b; + wire real valb = abs(fr(b)); + + initial begin + a = 0; + b = 0; + #1 if (vala !== 0) begin + $display("FAILED -- a=%b, vala=%b", a, vala); + $finish; + end + + #1 if (valb != 0) begin + $display("FAILED -- b=%g valb=%g", b, valb); + $finish; + end + + a = 1; + b = 1; + #1 if (vala !== 1) begin + $display("FAILED -- a=%b, vala=%b", a, vala); + $finish; + end + + #1 if (valb != 1) begin + $display("FAILED -- b=%g valb=%g", b, valb); + $finish; + end + + a = -1; + b = -1; + #1 if (vala !== 1) begin + $display("FAILED -- a=%b, vala=%b", a, vala); + $finish; + end + + #1 if (valb != 1) begin + $display("FAILED -- b=%g valb=%g", b, valb); + $finish; + end + + $display("PASSED"); + end + +endmodule // main diff --git a/ivtest/regress-vams.list b/ivtest/regress-vams.list index 68c4ae5ef..35f5b2ff1 100644 --- a/ivtest/regress-vams.list +++ b/ivtest/regress-vams.list @@ -81,6 +81,7 @@ value_range2 normal,-gverilog-ams ivltests value_range3 CE,-gverilog-ams ivltests vams_abs1 normal,-gverilog-ams ivltests vams_abs2 normal,-gverilog-ams ivltests +vams_abs3 normal,-gverilog-ams ivltests wreal normal,-gverilog-ams ivltests # Verilog functions added in a VAMS simulator constfunc6_ams normal ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index b70b1bd66..c02c18ea6 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -158,6 +158,7 @@ real_wire_force_rel CE ivltests tern8 CE ivltests v2005_math CE ivltests vams_abs2 CE,-gverilog-ams,-pallowsigned=1 ivltests +vams_abs3 CE,-gverilog-ams,-pallowsigned=1 ivltests vhdl_real CE,-g2009,ivltests/vhdl_real.vhd ivltests vhdl_unbounded CE,-g2009,ivltests/vhdl_unbounded.vhd ivltests wreal CE ivltests