From ef7ac5ed032f7276683f3b15c4251a8b0d190db3 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 5 Sep 2014 14:44:22 +0200 Subject: [PATCH 01/12] vhdlpp: Elaborate all types of initializing expressions. --- vhdlpp/vsignal.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index d03dae459..c9d77c56e 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -50,10 +50,7 @@ void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc) init_expr_ = bitstring; } else { - ExpAggregate*aggr = dynamic_cast(init_expr_); - if(aggr) { - aggr->elaborate_expr(ent, arc, peek_type()); - } + init_expr_->elaborate_expr(ent, arc, peek_type()); } } } From 94caa4881e35369b1ffd9e983942afd2aab2e9e8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 5 Sep 2014 14:58:48 +0200 Subject: [PATCH 02/12] vhdlpp: Added VTypeEnum::write_to_stream(). --- vhdlpp/vtype.h | 1 + vhdlpp/vtype_stream.cc | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 0fce73145..7ee6ca66a 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -240,6 +240,7 @@ class VTypeEnum : public VType { VTypeEnum(const std::list*names); ~VTypeEnum(); + void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; int emit_def(std::ostream&out, perm_string name) const; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 987582dbc..e184aa5bf 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -148,3 +148,18 @@ void VTypeRecord::element_t::write_to_stream(ostream&fd) const fd << name_ << ": "; type_->write_to_stream(fd); } + +void VTypeEnum::write_to_stream(std::ostream&fd) const +{ + fd << "("; + for (vector::const_iterator it = names_.begin(); + it != names_.end(); ++it) { + if(it != names_.begin()) + fd << ","; + + fd << *it; + + } + fd << ")"; +} + From 51b121ae7a85667a8afddac76ca21a5403fa5d2e Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 5 Sep 2014 14:59:20 +0200 Subject: [PATCH 03/12] vhdlpp: Added ExpBitString::write_to_stream(). --- vhdlpp/expression_stream.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 901bfab9e..f3e5b4ed0 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -112,9 +112,14 @@ void ExpAttribute::write_to_stream(ostream&) ivl_assert(*this, !"Not supported"); } -void ExpBitstring::write_to_stream(ostream&) +void ExpBitstring::write_to_stream(ostream&fd) { - ivl_assert(*this, !"Not supported"); + fd << "\""; + for(vector::const_iterator it = value_.begin(); + it != value_.end(); ++it) { + fd << *it; + } + fd << "\""; } void ExpCharacter::write_to_stream(ostream&fd) From a25cde3bc7c55df9d8be59f1ce554714ea4d4109 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 5 Sep 2014 15:06:57 +0200 Subject: [PATCH 04/12] vhdlpp: Added ExpString::write_to_stream(). --- vhdlpp/expression_stream.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index f3e5b4ed0..8f9830921 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -203,9 +203,14 @@ void ExpRelation::write_to_stream(ostream&) ivl_assert(*this, !"Not supported"); } -void ExpString::write_to_stream(ostream&) +void ExpString::write_to_stream(ostream&fd) { - ivl_assert(*this, !"Not supported"); + fd << "\""; + for(vector::const_iterator it = value_.begin(); + it != value_.end(); ++it) { + fd << *it; + } + fd << "\""; } void ExpUAbs::write_to_stream(ostream&fd) From f851fc6981171eb2b3d1f3f4c77b0a7ae6af82e4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 5 Sep 2014 15:07:42 +0200 Subject: [PATCH 05/12] vhdlpp: Fixed ExpAggregate::write_to_stream(). --- vhdlpp/expression_stream.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 8f9830921..0cd036fc6 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -29,6 +29,9 @@ void ExpAggregate::write_to_stream(ostream&fd) fd << "("; for (vector::const_iterator cur = elements_.begin() ; cur != elements_.end() ; ++cur) { + if(cur != elements_.begin()) + fd << ", "; + (*cur)->write_to_stream(fd); } fd << ")"; From 01b4d49d4a001a0dc8b1cf88a91f0b2969d3cbc3 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 9 Sep 2014 15:20:26 +0200 Subject: [PATCH 06/12] vhdlpp: Do not emit constants from packages. They are elaborated and emitted by architectures that make use of packages. --- vhdlpp/package_emit.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index 2cc3b91fb..db302cbad 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -52,18 +52,18 @@ int Package::emit_package(ostream&fd) const fd << " ;" << endl; } - for (map::const_iterator cur = use_constants_.begin() - ; cur != use_constants_.end() ; ++cur) { - fd << "localparam \\" << cur->first << " = "; - errors += cur->second->val->emit_package(fd); - fd << ";" << endl; - } - for (map::const_iterator cur = cur_constants_.begin() - ; cur != cur_constants_.end() ; ++cur) { - fd << "localparam " << cur->first << " = "; - errors += cur->second->val->emit_package(fd); - fd << ";" << endl; - } + //for (map::const_iterator cur = use_constants_.begin() + //; cur != use_constants_.end() ; ++cur) { + //fd << "localparam \\" << cur->first << " = "; + //errors += cur->second->val->emit_package(fd); + //fd << ";" << endl; + //} + //for (map::const_iterator cur = cur_constants_.begin() + //; cur != cur_constants_.end() ; ++cur) { + //fd << "localparam " << cur->first << " = "; + //errors += cur->second->val->emit_package(fd); + //fd << ";" << endl; + //} for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { From 251b75003f362946fdda289382c4e3496e0c3ac2 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 9 Sep 2014 16:29:31 +0200 Subject: [PATCH 07/12] vhdlpp: Skip writing '=>' for ExpAggregates if there are no fields specified. --- vhdlpp/expression_stream.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 0cd036fc6..a37fea2ed 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -44,7 +44,8 @@ void ExpAggregate::element_t::write_to_stream(ostream&fd) const (*cur)->write_to_stream(fd); } - fd << "=>"; + if(!fields_.empty()) + fd << "=>"; val_->write_to_stream(fd); } From a63289c2fc43869ca5b75cb50448e5152388c28f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 10 Sep 2014 14:32:02 +0200 Subject: [PATCH 08/12] vhdlpp: VTypeArray::range_t handles direction (to/downto). --- vhdlpp/parse.y | 2 +- vhdlpp/parse_misc.cc | 4 ++-- vhdlpp/vtype.cc | 3 ++- vhdlpp/vtype.h | 13 +++++++----- vhdlpp/vtype_stream.cc | 46 ++++++++++++++++++++---------------------- 5 files changed, 35 insertions(+), 33 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 0372d4925..906395f67 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -685,7 +685,7 @@ composite_type_definition /* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */ | K_array '(' index_subtype_definition_list ')' K_of subtype_indication { std::list r; - r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type + r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type VTypeArray*tmp = new VTypeArray($6, &r); $$ = tmp; } diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 3956b4a1a..7134faf76 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -70,7 +70,7 @@ void bind_architecture_to_entity(const char*ename, Architecture*arch) static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name, ScopeBase* /* scope */, Expression*array_left, - bool /* downto*/ , + bool downto, Expression*array_right) { const VType*base_type = parse_type_by_name(lex_strings.make(base_name)); @@ -97,7 +97,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n // For now, I only know how to handle 1 dimension assert(base_array->dimensions() == 1); - range[0] = VTypeArray::range_t(array_left, array_right); + range[0] = VTypeArray::range_t(array_left, array_right, downto); VTypeArray*subtype = new VTypeArray(base_array->element_type(), range, base_array->signed_vector()); return subtype; diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 7c0875f44..199d06fd7 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -88,7 +88,8 @@ VTypeArray::VTypeArray(const VType*element, std::list*r, bool sv) r->pop_front(); Expression*msb = curp->msb(); Expression*lsb = curp->lsb(); - ranges_[idx] = range_t(msb, lsb); + bool dir = curp->is_downto(); + ranges_[idx] = range_t(msb, lsb, dir); } } diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 7ee6ca66a..b0e540062 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -173,17 +173,19 @@ class VTypeArray : public VType { public: class range_t { public: - range_t() : msb_(0), lsb_(0) { } - range_t(Expression*m, Expression*l) : msb_(m), lsb_(l) { } + range_t(Expression*m = NULL, Expression*l = NULL, bool dir = true) : + msb_(m), lsb_(l), direction_(dir) { } - bool is_box() const { return msb_==0 && lsb_==0; } + inline bool is_box() const { return msb_==0 && lsb_==0; } + inline bool is_downto() const { return direction_; } - Expression* msb() const { return msb_; } - Expression* lsb() const { return lsb_; } + inline Expression* msb() const { return msb_; } + inline Expression* lsb() const { return lsb_; } private: Expression* msb_; Expression* lsb_; + bool direction_; }; public: @@ -210,6 +212,7 @@ class VTypeArray : public VType { bool can_be_packed() const { return etype_->can_be_packed(); } private: + void write_range_to_stream_(std::ostream&fd) const; const VType*etype_; std::vector ranges_; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index e184aa5bf..d9fef3df2 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -42,18 +42,7 @@ void VTypeArray::write_to_stream(ostream&fd) const if (etype_ == &primitive_STDLOGIC) { fd << "std_logic_vector"; if (! ranges_.empty() && ! ranges_[0].is_box()) { - assert(ranges_.size() < 2); - fd << " ("; - if (ranges_[0].msb()) - ranges_[0].msb()->write_to_stream(fd); - else - fd << "<>"; - fd << " downto "; - if (ranges_[0].lsb()) - ranges_[0].lsb()->write_to_stream(fd); - else - fd << "<>"; - fd << ") "; + write_range_to_stream_(fd); } return; } @@ -64,18 +53,7 @@ void VTypeArray::write_to_stream(ostream&fd) const if (ranges_[0].is_box()) { fd << "(INTEGER range <>) "; } else { - assert(ranges_[0].msb() && ranges_[0].lsb()); - fd << "("; - if (ranges_[0].msb()) - ranges_[0].msb()->write_to_stream(fd); - else - fd << "<>"; - fd << " downto "; - if (ranges_[0].lsb()) - ranges_[0].lsb()->write_to_stream(fd); - else - fd << "<>"; - fd << ") "; + write_range_to_stream_(fd); } } @@ -83,6 +61,26 @@ void VTypeArray::write_to_stream(ostream&fd) const etype_->write_to_stream(fd); } +void VTypeArray::write_range_to_stream_(std::ostream&fd) const +{ + assert(ranges_.size() < 2); + assert(ranges_[0].msb() && ranges_[0].lsb()); + + fd << "("; + if (ranges_[0].msb()) + ranges_[0].msb()->write_to_stream(fd); + else + fd << "<>"; + + fd << (ranges_[0].is_downto() ? " downto " : " to "); + + if (ranges_[0].lsb()) + ranges_[0].lsb()->write_to_stream(fd); + else + fd << "<>"; + fd << ") "; +} + void VTypeDef::write_type_to_stream(ostream&fd) const { type_->write_to_stream(fd); From c98c3e5d14fd1cda4c4ba7a6344c9916ae43a78c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 10 Sep 2014 16:02:59 +0200 Subject: [PATCH 09/12] vhdlpp: Inlined a few functions. --- vhdlpp/vtype.cc | 9 --------- vhdlpp/vtype.h | 7 ++++--- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 199d06fd7..07dfc7e28 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -98,15 +98,6 @@ VTypeArray::~VTypeArray() { } -size_t VTypeArray::dimensions() const -{ - return ranges_.size(); -} - -const VType* VTypeArray::element_type() const -{ - return etype_; -} void VTypeArray::show(ostream&out) const { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index b0e540062..bfaae2f61 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -197,13 +197,14 @@ class VTypeArray : public VType { void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; - size_t dimensions() const; + inline size_t dimensions() const { return ranges_.size(); }; const range_t&dimension(size_t idx) const { return ranges_[idx]; } - bool signed_vector() const { return signed_flag_; } + inline bool signed_vector() const { return signed_flag_; } - const VType* element_type() const; + // returns the type of element held in the array + inline const VType* element_type() const { return etype_; } int emit_def(std::ostream&out, perm_string name) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; From 22d18cb28dd499d11404e1f3354fb8c5beaa7cf5 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 15 Sep 2014 10:57:08 +0200 Subject: [PATCH 10/12] vhdlpp: Typedefs in packages are emitted before constants. --- vhdlpp/package.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index d3d4a8b06..68c8acee1 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -66,21 +66,6 @@ void Package::write_to_stream(ostream&fd) const fd << "type " << cur->first << ";" << endl; } - for (map::const_iterator cur = cur_constants_.begin() - ; cur != cur_constants_.end() ; ++ cur) { - if (cur->second==0 || cur->second->typ==0) { - fd << "-- const " << cur->first - << " has errors." << endl; - continue; - } - - fd << "constant " << cur->first << ": "; - cur->second->typ->write_to_stream(fd); - fd << " := "; - cur->second->val->write_to_stream(fd); - fd << ";" << endl; - } - for (map::const_iterator cur = use_types_.begin() ; cur != use_types_.end() ; ++cur) { @@ -108,6 +93,21 @@ void Package::write_to_stream(ostream&fd) const fd << ";" << endl; } + for (map::const_iterator cur = cur_constants_.begin() + ; cur != cur_constants_.end() ; ++ cur) { + if (cur->second==0 || cur->second->typ==0) { + fd << "-- const " << cur->first + << " has errors." << endl; + continue; + } + + fd << "constant " << cur->first << ": "; + cur->second->typ->write_to_stream(fd); + fd << " := "; + cur->second->val->write_to_stream(fd); + fd << ";" << endl; + } + for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++cur) { cur->second->write_to_stream(fd); From cb03802a175a21e4303701304ff57f5c915fd7a2 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 15 Sep 2014 11:08:14 +0200 Subject: [PATCH 11/12] vhdlpp: Added VTypeArray::basic_type() to cope with arrays based on typedefs. --- vhdlpp/expression_emit.cc | 2 +- vhdlpp/vtype.cc | 23 +++++++++++++++++++++++ vhdlpp/vtype.h | 6 ++++++ vhdlpp/vtype_emit.cc | 6 +----- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index f2e312f8a..63bde19e1 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -767,7 +767,7 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA int errors = 0; assert(arr->dimensions() == 1); - const VTypePrimitive*etype = dynamic_cast (arr->element_type()); + const VTypePrimitive*etype = dynamic_cast (arr->basic_type()); assert(etype); // Detect the special case that this is an array of diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 07dfc7e28..208482877 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -98,6 +98,29 @@ VTypeArray::~VTypeArray() { } +const VType* VTypeArray::basic_type(bool typedef_allowed) const +{ + const VType*t = etype_; + const VTypeDef*tdef = NULL; + bool progress = false; + + do { + progress = false; + + if((tdef = dynamic_cast(t))) { + t = tdef->peek_definition(); + } + + if(const VTypeArray*arr = dynamic_cast(t)) { + t = arr->element_type(); + progress = true; + } else if(tdef) { // return the typedef if it does not define an array + t = typedef_allowed ? tdef : tdef->peek_definition(); + } + } while(progress); + + return t; +} void VTypeArray::show(ostream&out) const { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index bfaae2f61..09a44231d 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -206,6 +206,12 @@ class VTypeArray : public VType { // returns the type of element held in the array inline const VType* element_type() const { return etype_; } + // returns the basic type of element held in the array + // (unfolds typedefs and multidimensional arrays) + // typedef_allowed decides if VTypeDef can be returned or should + // it be unfolded + const VType* basic_type(bool typedef_allowed = true) const; + int emit_def(std::ostream&out, perm_string name) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; int emit_dimensions(std::ostream&out) const; diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index a723dbda5..9dc17b5f2 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -60,12 +60,8 @@ int VTypeArray::emit_def(ostream&out, perm_string name) const { int errors = 0; - const VTypeArray*cur = this; - while (const VTypeArray*sub = dynamic_cast (cur->etype_)) { - cur = sub; - } + const VType*raw_base = basic_type(); - const VType*raw_base = cur->etype_; const VTypePrimitive*base = dynamic_cast (raw_base); if (base) { From e330a0bd6efdd1967d42bb22fc5e8d887c128a0f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 15 Sep 2014 11:20:39 +0200 Subject: [PATCH 12/12] vhdlpp: Corrected VTypeArray::write_to_stream(). Now it outputs "typedef(range)" instead of "array (range) of type". --- vhdlpp/parse_misc.cc | 9 +++++++-- vhdlpp/vtype_stream.cc | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 7134faf76..734443d3e 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -82,7 +82,8 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n assert(array_left==0 || array_right!=0); - // unfold typedef, if it is the case + // unfold typedef, there might be VTypeArray inside + const VType*origin_type = base_type; const VTypeDef*type_def = dynamic_cast (base_type); if (type_def) { base_type = type_def->peek_definition(); @@ -99,7 +100,11 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n range[0] = VTypeArray::range_t(array_left, array_right, downto); - VTypeArray*subtype = new VTypeArray(base_array->element_type(), range, base_array->signed_vector()); + // use typedef as the element type if possible + const VType*element = type_def ? origin_type : base_array->element_type(); + + VTypeArray*subtype = new VTypeArray(element, range, + base_array->signed_vector()); return subtype; } diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index d9fef3df2..1392a6c50 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -47,7 +47,14 @@ void VTypeArray::write_to_stream(ostream&fd) const return; } - fd << "array "; + bool typedefed = false; + if(const VTypeDef*tdef = dynamic_cast(etype_)) { + tdef->write_to_stream(fd); + typedefed = true; + } else { + fd << "array "; + } + if (! ranges_.empty()) { assert(ranges_.size() < 2); if (ranges_[0].is_box()) { @@ -57,8 +64,10 @@ void VTypeArray::write_to_stream(ostream&fd) const } } - fd << "of "; - etype_->write_to_stream(fd); + if(!typedefed) { + fd << "of "; + etype_->write_to_stream(fd); + } } void VTypeArray::write_range_to_stream_(std::ostream&fd) const