bvt float_utilst::from_unsigned_integer(const bvt &src) { unbiased_floatt result; result.fraction=src; // build an exponent (unbiased) -- this is signed! result.exponent= bv_utils.build_constant( src.size()-1, address_bits(src.size()-1).to_long()+1); result.sign=const_literal(false); return rounder(result); }
bvt float_utilst::from_signed_integer(const bvt &src) { unbiased_floatt result; // we need to convert negative integers result.sign=sign_bit(src); result.fraction=bv_utils.absolute_value(src); // build an exponent (unbiased) -- this is signed! result.exponent= bv_utils.build_constant( src.size()-1, address_bits(src.size()-1).to_long()+1); return rounder(result); }
bvt float_utilst::limit_distance( const bvt &dist, mp_integer limit) { std::size_t nb_bits=integer2unsigned(address_bits(limit)); bvt upper_bits=dist; upper_bits.erase(upper_bits.begin(), upper_bits.begin()+nb_bits); literalt or_upper_bits=prop.lor(upper_bits); bvt lower_bits=dist; lower_bits.resize(nb_bits); bvt result; result.resize(lower_bits.size()); // bitwise or with or_upper_bits for(std::size_t i=0; i<result.size(); i++) result[i]=prop.lor(lower_bits[i], or_upper_bits); return result; }
bvt float_utilst::rounder(const unbiased_floatt &src) { // incoming: some fraction (with explicit 1), // some exponent without bias // outgoing: rounded, with right size, with hidden bit, bias bvt aligned_fraction=src.fraction, aligned_exponent=src.exponent; { std::size_t exponent_bits= std::max((std::size_t)integer2size_t(address_bits(spec.f)), (std::size_t)spec.e)+1; // before normalization, make sure exponent is large enough if(aligned_exponent.size()<exponent_bits) { // sign extend aligned_exponent= bv_utils.sign_extension(aligned_exponent, exponent_bits); } } // align it! normalization_shift(aligned_fraction, aligned_exponent); denormalization_shift(aligned_fraction, aligned_exponent); unbiased_floatt result; result.fraction=aligned_fraction; result.exponent=aligned_exponent; result.sign=src.sign; result.NaN=src.NaN; result.infinity=src.infinity; round_fraction(result); round_exponent(result); return pack(bias(result)); }
void float_utilst::normalization_shift(bvt &fraction, bvt &exponent) { #if 0 // this thing is quadratic! bvt new_fraction=prop.new_variables(fraction.size()); bvt new_exponent=prop.new_variables(exponent.size()); // i is the shift distance for(std::size_t i=0; i<fraction.size(); i++) { bvt equal; // the bits above need to be zero for(std::size_t j=0; j<i; j++) equal.push_back( !fraction[fraction.size()-1-j]); // this one needs to be one equal.push_back(fraction[fraction.size()-1-i]); // iff all of that holds, we shift here! literalt shift=prop.land(equal); // build shifted value bvt shifted_fraction=bv_utils.shift(fraction, bv_utilst::LEFT, i); bv_utils.cond_implies_equal(shift, shifted_fraction, new_fraction); // build new exponent bvt adjustment=bv_utils.build_constant(-i, exponent.size()); bvt added_exponent=bv_utils.add(exponent, adjustment); bv_utils.cond_implies_equal(shift, added_exponent, new_exponent); } // Fraction all zero? It stays zero. // The exponent is undefined in that case. literalt fraction_all_zero=bv_utils.is_zero(fraction); bvt zero_fraction; zero_fraction.resize(fraction.size(), const_literal(false)); bv_utils.cond_implies_equal(fraction_all_zero, zero_fraction, new_fraction); fraction=new_fraction; exponent=new_exponent; #else // n-log-n alignment shifter. // The worst-case shift is the number of fraction // bits minus one, in case the faction is one exactly. assert(!fraction.empty()); unsigned depth=integer2unsigned(address_bits(fraction.size()-1)); if(exponent.size()<depth) exponent=bv_utils.sign_extension(exponent, depth); bvt exponent_delta=bv_utils.zeros(exponent.size()); for(int d=depth-1; d>=0; d--) { std::size_t distance=(1<<d); assert(fraction.size()>distance); // check if first 'distance'-many bits are zeros const bvt prefix=bv_utils.extract_msb(fraction, distance); literalt prefix_is_zero=bv_utils.is_zero(prefix); // If so, shift the zeros out left by 'distance'. // Otherwise, leave as is. const bvt shifted= bv_utils.shift(fraction, bv_utilst::LEFT, distance); fraction= bv_utils.select(prefix_is_zero, shifted, fraction); // add corresponding weight to exponent assert(d<(signed)exponent_delta.size()); exponent_delta[d]=prefix_is_zero; } exponent=bv_utils.sub(exponent, exponent_delta); #endif }
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { // check cache first std::pair<cachet::iterator, bool> cache_result= cache.insert(std::pair<typet, entryt>(type, entryt())); entryt &entry=cache_result.first->second; if(!cache_result.second) // found! return entry; entry.total_width=0; const irep_idt type_id=type.id(); if(type_id==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); std::size_t offset=0; entry.members.resize(components.size()); for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].offset=offset; entry.members[i].width=sub_width; offset+=sub_width; } entry.total_width=offset; } else if(type_id==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); entry.members.resize(components.size()); std::size_t max_width=0; for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].width=sub_width; max_width=std::max(max_width, sub_width); } entry.total_width=max_width; } else if(type_id==ID_bool) entry.total_width=1; else if(type_id==ID_c_bool) { entry.total_width=to_c_bool_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_signedbv) { entry.total_width=to_signedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_unsignedbv) { entry.total_width=to_unsignedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_floatbv) { entry.total_width=to_floatbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_fixedbv) { entry.total_width=to_fixedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_bv) { entry.total_width=to_bv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_verilogbv) { // we encode with two bits entry.total_width=type.get_unsigned_int(ID_width)*2; assert(entry.total_width!=0); } else if(type_id==ID_range) { mp_integer from=string2integer(type.get_string(ID_from)), to=string2integer(type.get_string(ID_to)); mp_integer size=to-from+1; if(size>=1) { entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } } else if(type_id==ID_array) { const array_typet &array_type=to_array_type(type); std::size_t sub_width=operator()(array_type.subtype()); mp_integer array_size; if(to_integer(array_type.size(), array_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=array_size*sub_width; if(total>(1<<30)) // realistic limit throw "array too large for flattening"; entry.total_width=integer2unsigned(total); } } else if(type_id==ID_vector) { const vector_typet &vector_type=to_vector_type(type); std::size_t sub_width=operator()(vector_type.subtype()); mp_integer vector_size; if(to_integer(vector_type.size(), vector_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=vector_size*sub_width; if(total>(1<<30)) // realistic limit throw "vector too large for flattening"; entry.total_width=integer2unsigned(vector_size*sub_width); } } else if(type_id==ID_complex) { std::size_t sub_width=operator()(type.subtype()); entry.total_width=integer2unsigned(2*sub_width); } else if(type_id==ID_code) { } else if(type_id==ID_enum) { // get number of necessary bits std::size_t size=type.find(ID_elements).get_sub().size(); entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } else if(type_id==ID_c_enum) { // these have a subtype entry.total_width=type.subtype().get_unsigned_int(ID_width); assert(entry.total_width!=0); } else if(type_id==ID_incomplete_c_enum) { // no width } else if(type_id==ID_pointer || type_id==ID_reference) { entry.total_width=config.ansi_c.pointer_width; } else if(type_id==ID_symbol) entry=get_entry(ns.follow(type)); else if(type_id==ID_struct_tag) entry=get_entry(ns.follow_tag(to_struct_tag_type(type))); else if(type_id==ID_union_tag) entry=get_entry(ns.follow_tag(to_union_tag_type(type))); else if(type_id==ID_c_enum_tag) entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type))); else if(type_id==ID_c_bit_field) { entry.total_width=to_c_bit_field_type(type).get_width(); } return entry; }