/// <summary> /// Tries to find a serializer for the specified type. To do so, it looks for the <c>SLVSerializable</c> attribute /// in both the type attributes and <c>StdLogicVector</c> attributes. /// </summary> /// <param name="type">type of object to serialize/deserialize</param> /// <returns>a suitable serializer instance, or <c>null</c> if noch such was found</returns> public static ISerializer TryGetSerializer(Type type) { object[] tattrs = type.GetCustomAttributes(typeof(SLVSerializable), false); object[] sattrs = typeof(StdLogicVector).GetCustomAttributes(typeof(SLVSerializable), false); SLVSerializable result = tattrs.Union(sattrs).Cast <SLVSerializable>().Where(a => a.ObjectType.Equals(type)).FirstOrDefault(); if (result == null) { return(null); } else { return((ISerializer)Activator.CreateInstance(result.SerializerType)); } }
/// <summary> /// Computes a memory layout for a given type descriptor. /// </summary> /// <param name="td">type descriptor to layout</param> /// <param name="info">marshalling information</param> /// <returns>memory layout</returns> public static MemoryLayout Layout(TypeDescriptor td, IMarshalInfo info) { Type type = td.CILType; ISerializer ser = SLVSerializable.TryGetSerializer(type); if (ser != null) { object sample = td.GetSampleInstance(); return(CreatePrimLayout(ser.Serialize(sample).Size, td, info)); } if (ser == null && td.HasIntrinsicTypeOverride) { throw new InvalidOperationException("Type " + type.Name + " has intrinsic type override but no serializer"); } if (type.IsEnum) { return(new EnumMemoryLayout(td, info)); } if (type.IsArray) { td.AssertStatic(); TypeDescriptor elemTd = td.Element0Type; MemoryLayout elemLayout = Layout(elemTd, info); ulong subStride = elemLayout.SizeInBits; if (subStride == 0) { return(new EmptyMemoryLayout(td) { Size = 0, SizeInBits = 0 }); } ulong[] strides = new ulong[type.GetArrayRank()]; ulong elemsPerWord = (ulong)info.WordSize / elemLayout.SizeInBits; ulong wordsPerElem = elemLayout.Size; if (elemsPerWord > 1) { if (info.UseArraySubWordAlignment) { if (info.UseArrayDimPow2Alignment) { elemsPerWord = MathExt.FloorPow2(elemsPerWord); subStride = info.WordSize / elemsPerWord; } } else { elemsPerWord = 1; } } ulong dimSize = (ulong)(int)td.TypeParams.Last(); ulong dimWords; if (elemsPerWord <= 1) { subStride = 0; if (info.UseArrayDimPow2Alignment) { wordsPerElem = MathExt.CeilPow2(wordsPerElem); } dimWords = wordsPerElem * dimSize; } else { wordsPerElem = 0; dimWords = (dimSize + elemsPerWord - 1) / elemsPerWord; } strides[strides.Length - 1] = wordsPerElem; for (int i = strides.Length - 2; i >= 0; i--) { if (info.UseArrayDimPow2Alignment) { dimWords = MathExt.CeilPow2(dimWords); } strides[i] = dimWords; dimSize = (ulong)(int)td.TypeParams[i]; dimWords *= dimSize; } return(new ArrayMemoryLayout(td, info.WordSize, strides, subStride, (uint)elemsPerWord, (uint)wordsPerElem, elemLayout) { Size = dimWords, SizeInBits = dimWords * info.WordSize }); } if (type.IsValueType && !type.IsPrimitive) { StructMemoryLayout ml = new StructMemoryLayout(td); FieldInfo[] fields = type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); ulong offset = 0; foreach (FieldInfo field in fields) { TypeDescriptor fieldTd = td.GetFieldType(field); MemoryLayout fieldLayout = Layout(fieldTd, info); FieldLocation fieldLoc = new FieldLocation(field, fieldLayout, offset); ml.AddLocation(fieldLoc); offset += fieldLayout.Size; } ml.Size = offset; ml.SizeInBits = offset * info.WordSize; return(ml); } throw new InvalidOperationException("Unable to create data layout for type " + type.Name); }