diff --git a/ivl.def b/ivl.def index d47294db9..3f8e8d1a7 100644 --- a/ivl.def +++ b/ivl.def @@ -313,6 +313,7 @@ ivl_type_packed_msb ivl_type_prop_name ivl_type_prop_type ivl_type_properties +ivl_type_signed ivl_udp_init ivl_udp_file diff --git a/ivl_target.h b/ivl_target.h index 9a3343d08..38056da91 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -2232,6 +2232,10 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net); * Return the type of the element of an array. This is only valid * for array types. * + * ivl_type_signed + * Return TRUE if the type represents a signed packed vector or + * signed atomic type, and FALSE otherwise. + * * SEMANTIC NOTES * * Class types have names and properties. @@ -2241,6 +2245,7 @@ extern ivl_type_t ivl_type_element(ivl_type_t net); extern unsigned ivl_type_packed_dimensions(ivl_type_t net); extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim); extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim); +extern int ivl_type_signed(ivl_type_t net); extern const char* ivl_type_name(ivl_type_t net); extern int ivl_type_properties(ivl_type_t net); extern const char* ivl_type_prop_name(ivl_type_t net, int idx); diff --git a/netvector.cc b/netvector.cc index de67bba69..cb602d9a7 100644 --- a/netvector.cc +++ b/netvector.cc @@ -23,10 +23,10 @@ using namespace std; netvector_t netvector_t::atom2s32 (IVL_VT_BOOL, 31, 0, true); netvector_t netvector_t::atom2u32 (IVL_VT_BOOL, 31, 0, false); -netvector_t netvector_t::atom2s16 (IVL_VT_BOOL, 16, 0, true); -netvector_t netvector_t::atom2u16 (IVL_VT_BOOL, 16, 0, false); -netvector_t netvector_t::atom2s8 (IVL_VT_BOOL, 8, 0, true); -netvector_t netvector_t::atom2u8 (IVL_VT_BOOL, 8, 0, false); +netvector_t netvector_t::atom2s16 (IVL_VT_BOOL, 15, 0, true); +netvector_t netvector_t::atom2u16 (IVL_VT_BOOL, 15, 0, false); +netvector_t netvector_t::atom2s8 (IVL_VT_BOOL, 7, 0, true); +netvector_t netvector_t::atom2u8 (IVL_VT_BOOL, 7, 0, false); netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb, bool flag) : type_(type), signed_(flag), isint_(false), is_scalar_(false) diff --git a/t-dll-api.cc b/t-dll-api.cc index 52060e793..bbd8490f7 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2896,3 +2896,8 @@ extern "C" ivl_type_t ivl_type_prop_type(ivl_type_t net, int idx) return class_type->get_prop_type(idx); } + +extern "C" int ivl_type_signed(ivl_type_t net) +{ + return net->get_signed()? 1 : 0; +} diff --git a/tgt-vvp/draw_class.c b/tgt-vvp/draw_class.c index a4d6b6894..459c9a43f 100644 --- a/tgt-vvp/draw_class.c +++ b/tgt-vvp/draw_class.c @@ -24,10 +24,48 @@ # include # include +static void show_prop_type_vector(ivl_type_t ptype) +{ + ivl_variable_type_t data_type = ivl_type_base(ptype); + unsigned packed_dimensions = ivl_type_packed_dimensions(ptype); + assert(packed_dimensions < 2); + + char*signed_flag = ivl_type_signed(ptype)? "s" : ""; + char code = data_type==IVL_VT_BOOL? 'b' : 'L'; + + if (packed_dimensions == 0) { + fprintf(vvp_out, "\"%s%c1\"", signed_flag, code); + + } else { + assert(packed_dimensions == 1); + assert(ivl_type_packed_lsb(ptype,0) == 0); + assert(ivl_type_packed_msb(ptype,0) >= 0); + + fprintf(vvp_out, "\"%s%c%d\"", signed_flag, code, + ivl_type_packed_msb(ptype,0)+1); + } +} + static void show_prop_type(ivl_type_t ptype) { - // XXXX: For now, assume all properties are 32bit integers. - fprintf(vvp_out, "\"b32\""); + ivl_variable_type_t data_type = ivl_type_base(ptype); + + switch (data_type) { + case IVL_VT_REAL: + fprintf(vvp_out, "\"r\""); + break; + case IVL_VT_STRING: + fprintf(vvp_out, "\"S\""); + break; + case IVL_VT_BOOL: + case IVL_VT_LOGIC: + show_prop_type_vector(ptype); + break; + default: + assert(0); + fprintf(vvp_out, "\"\""); + break; + } } void draw_class_in_scope(ivl_type_t classtype) diff --git a/vvp/class_type.cc b/vvp/class_type.cc index 9606d4ca2..e061fdd6a 100644 --- a/vvp/class_type.cc +++ b/vvp/class_type.cc @@ -21,6 +21,7 @@ # include "compile.h" # include "vpi_priv.h" # include "config.h" +# include #ifdef CHECK_WITH_VALGRIND # include "vvp_cleanup.h" #endif @@ -28,15 +29,186 @@ using namespace std; -class_type::class_type(const string&nam, size_t nprop) -: class_name_(nam), properties_(nprop) +/* + * This class_property_t class is an abstract base class for + * representing a property of an instance. The definition keeps and + * array (of pointers) of these in order to define the the class. + */ +class class_property_t { + public: + explicit inline class_property_t() { } + virtual ~class_property_t() =0; + // How much space does an instance of this property require? + virtual size_t instance_size() const =0; + + void set_offset(size_t off) { offset_ = off; } + + public: + virtual void construct(char*buf) const; + virtual void destruct(char*buf) const; + + virtual void set_vec4(char*buf, const vvp_vector4_t&val); + virtual void get_vec4(char*buf, vvp_vector4_t&val); + + protected: + size_t offset_; +}; + +class_property_t::~class_property_t() { } -void class_type::set_property(size_t idx, const string&name) +void class_property_t::construct(char*) const +{ +} + +void class_property_t::destruct(char*) const +{ +} + +void class_property_t::set_vec4(char*, const vvp_vector4_t&) +{ + assert(0); +} + +void class_property_t::get_vec4(char*, vvp_vector4_t&) +{ + assert(0); +} + +/* + */ +template class property_atom : public class_property_t { + public: + inline explicit property_atom(void) { } + ~property_atom() { } + + size_t instance_size() const { return sizeof(T); } + + public: + void construct(char*buf) const + { T*tmp = reinterpret_cast (buf+offset_); + *tmp = 0; + } + + void set_vec4(char*buf, const vvp_vector4_t&val) + { + T*tmp = reinterpret_cast (buf+offset_); + bool flag = vector4_to_value(val, *tmp, true, false); + assert(flag); + } + + void get_vec4(char*buf, vvp_vector4_t&val) + { + T*src = reinterpret_cast (buf+offset_); + const size_t tmp_cnt = (sizeof(T) + sizeof(unsigned long)-1)/sizeof(unsigned long); + unsigned long tmp[tmp_cnt]; + tmp[0] = src[0]; + for (size_t idx = 1 ; idx < tmp_cnt ; idx += 1) + tmp[idx] = 0; + + val.resize(8*sizeof(T)); + val.setarray(0, val.size(), tmp); + } +}; + +/* **** */ + +class_type::class_type(const string&nam, size_t nprop) +: class_name_(nam), properties_(nprop) +{ + instance_size_ = 0; +} + +void class_type::set_property(size_t idx, const string&name, const string&type) { assert(idx < properties_.size()); properties_[idx].name = name; + + if (type == "b8") + properties_[idx].type = new property_atom; + else if (type == "b16") + properties_[idx].type = new property_atom; + else if (type == "b32") + properties_[idx].type = new property_atom; + else if (type == "b64") + properties_[idx].type = new property_atom; + else if (type == "sb8") + properties_[idx].type = new property_atom; + else if (type == "sb16") + properties_[idx].type = new property_atom; + else if (type == "sb32") + properties_[idx].type = new property_atom; + else if (type == "sb64") + properties_[idx].type = new property_atom; + else + properties_[idx].type = 0; +} + +void class_type::finish_setup(void) +{ + map > size_map; + // Add up all the sizes to get a total instance size. This + // figures out how much memory a complete instance will need. + size_t accum = 0; + for (size_t idx = 0 ; idx < properties_.size() ; idx += 1) { + size_t instance_size = properties_[idx].type->instance_size(); + accum += instance_size; + size_map[instance_size].push_back(idx); + } + + instance_size_ = accum; + + // Now allocate the properties to offsets within an instance + // space. Allocate the properties largest objects first so + // that they are assured better alignment. + accum = 0; + for (map >::reverse_iterator cur = size_map.rbegin() + ; cur != size_map.rend() ; ++ cur) { + for (size_t idx = 0 ; idx < cur->second.size() ; idx += 1) { + size_t pid = cur->second[idx]; + class_property_t*ptype = properties_[pid].type; + assert(ptype->instance_size() == cur->first); + ptype->set_offset(accum); + accum += cur->first; + } + } +} + +class_type::inst_t class_type::instance_new() const +{ + char*buf = new char [instance_size_]; + + for (size_t idx = 0 ; idx < properties_.size() ; idx += 1) + properties_[idx].type->construct(buf); + + return reinterpret_cast (buf); +} + +void class_type::instance_delete(class_type::inst_t obj) const +{ + char*buf = reinterpret_cast (obj); + + for (size_t idx = 0 ; idx < properties_.size() ; idx += 1) + properties_[idx].type->destruct(buf); + + delete[]buf; +} + +void class_type::set_vec4(class_type::inst_t obj, size_t pid, + const vvp_vector4_t&val) const +{ + char*buf = reinterpret_cast (obj); + assert(pid < properties_.size()); + properties_[pid].type->set_vec4(buf, val); +} + +void class_type::get_vec4(class_type::inst_t obj, size_t pid, + vvp_vector4_t&val) const +{ + char*buf = reinterpret_cast (obj); + assert(pid < properties_.size()); + properties_[pid].type->get_vec4(buf, val); } int class_type::get_type_code(void) const @@ -58,7 +230,7 @@ void compile_class_start(char*lab, char*nam, unsigned ntype) void compile_class_property(unsigned idx, char*nam, char*typ) { assert(compile_class); - compile_class->set_property(idx, nam); + compile_class->set_property(idx, nam, typ); delete[]nam; delete[]typ; } @@ -67,6 +239,8 @@ void compile_class_done(void) { struct __vpiScope*scope = vpip_peek_current_scope(); assert(scope); + assert(compile_class); + compile_class->finish_setup(); scope->classes[compile_class->class_name()] = compile_class; compile_class = 0; } diff --git a/vvp/class_type.h b/vvp/class_type.h index 5a27e5407..f7a5564d1 100644 --- a/vvp/class_type.h +++ b/vvp/class_type.h @@ -23,6 +23,9 @@ # include # include "vpi_priv.h" +class class_property_t; +class vvp_vector4_t; + /* * This represents the TYPE information for a class. A %new operator * uses this information to figure out how to construct an actual @@ -30,6 +33,10 @@ */ class class_type : public __vpiHandle { + public: + struct inst_x; + typedef inst_x*inst_t; + public: explicit class_type(const std::string&nam, size_t nprop); @@ -41,8 +48,21 @@ class class_type : public __vpiHandle { // Set the details about the property. This is used during // parse of the .vvp file to fill in the details of the // property for the class definition. - void set_property(size_t idx, const std::string&name); + void set_property(size_t idx, const std::string&name, const std::string&type); + // This method is called after all the properties are + // defined. This calculates information about the defintion. + void finish_setup(void); + + public: + // Constructures and destructors for making instances. + inst_t instance_new() const; + void instance_delete(inst_t) const; + + void set_vec4(inst_t inst, size_t pid, const vvp_vector4_t&val) const; + void get_vec4(inst_t inst, size_t pid, vvp_vector4_t&val) const; + + public: // VPI related methods int get_type_code(void) const; private: @@ -50,8 +70,10 @@ class class_type : public __vpiHandle { struct prop_t { std::string name; + class_property_t*type; }; std::vector properties_; + size_t instance_size_; }; #endif diff --git a/vvp/vvp_cobject.cc b/vvp/vvp_cobject.cc index db379e65f..b2d85e822 100644 --- a/vvp/vvp_cobject.cc +++ b/vvp/vvp_cobject.cc @@ -25,33 +25,22 @@ using namespace std; vvp_cobject::vvp_cobject(const class_type*defn) -: defn_(defn), properties_(new int32_t[defn->property_count()]) +: defn_(defn), properties_(defn->instance_new()) { } vvp_cobject::~vvp_cobject() { - delete[]properties_; + defn_->instance_delete(properties_); properties_ = 0; } void vvp_cobject::set_vec4(size_t pid, const vvp_vector4_t&val) { - assert(pid < defn_->property_count()); - - int32_t tmp; - bool flag = vector4_to_value(val, tmp, true, false); - assert(flag); - - properties_[pid] = tmp; + defn_->set_vec4(properties_, pid, val); } void vvp_cobject::get_vec4(size_t pid, vvp_vector4_t&val) { - assert(pid < defn_->property_count()); - - unsigned long tmp[1]; - tmp[0] = properties_[pid]; - val.resize(32); - val.setarray(0, 32, tmp); + defn_->get_vec4(properties_, pid, val); } diff --git a/vvp/vvp_cobject.h b/vvp/vvp_cobject.h index 66b18647d..2cb9b7b00 100644 --- a/vvp/vvp_cobject.h +++ b/vvp/vvp_cobject.h @@ -21,8 +21,8 @@ # include # include "vvp_object.h" +# include "class_type.h" -class class_type; class vvp_vector4_t; class vvp_cobject : public vvp_object { @@ -37,7 +37,7 @@ class vvp_cobject : public vvp_object { private: const class_type* defn_; // For now, only support 32bit bool signed properties. - int32_t*properties_; + class_type::inst_t properties_; }; #endif