Implementing algorithms for field-programmable gate arrays using a hardware description language is a complex task. Therefore, it would be useful to have a tool that can efficiently translate an algorithm from a high-level language to a hardware description language. In this paper we consider the C-to-HDL which can translate C functions into Verilog modules, the translation process, and two important optimizations implemented on hardware description level: assignment inlining and loop pipelining. The basic structure and ABI interface of C-to-HDL follows that of the C-to-Verilog translator which inspired us for creating our tool. We also use LLVM infrastructure for translating LLVM bitcode representation into the Verilog code. Simple arithmetic operations are executed within a single cycle, while for complex arithmetic operations and loads/stores from/to memory, first, a set of assignments loading instruction operands, memory address, and memory access mode (read or write) is generated and placed on the first cycle of executing the instructions, and second, the final assignment transferring the operation result to a virtual register is generated.
The following optimizations are implemented and greatly improve the execution performance. Instruction scheduling is performed, taking into account that the number of instructions executed in parallel is only limited by the FPGA free chip space; the memory operations have limits given by the number of memory channels and blocks on the FPGA. If possible, assignments of temporary registers are inlined to make the more complex operations, but without producing too long dependence chains and unwanted limiting of the FPGA frequency. Finally, software pipelining following the usual modulo scheduling scheme is also performed with the same resource constraint limit relaxations as described for instruction scheduling.
Experimental results demonstrate that these optimizations significantly improve (up to 4x) the performance of generated code.
This paper presents a method for raising the level of abstraction of a program execution trace by building of an algorithm model.
Dynamic analysis of executable files is often used to understand the logic of a program in the absence of source code. One of dynamic analysis methods is analysis of program execution traces containing register values and sequence of instructions executed by the processor. Traces are difficult for understanding because of the large amount of information.
First stage of building an algorithm model is identification of function calls in the trace. Input and output parameters are determined for each call. If the trace has got several calls for the same function, the information about them is combined, defining low-level parameters, return value, and dependencies between inputs and outputs.
Second stage is variable recovery. Low-level data elements are mapped on variables. Each processor has a fixed set of registers and limited memory and the number of higher-level variables in the program is not limited. Variable lifetime is evaluated for mapping variables to their locations. Lifetime is a range of trace step indexes from variable creation to its last usage. Return value and parameters of the function are recovered using its calling convention.
Third stage is examination of library calls that are used in the trace. Symbolic information can be extracted from binary libraries and added to the corresponding functions in the trace. Header files are available for some libraries. Full high level function prototypes can be found from them and mapped to the trace.
This allows us to get high level types of parameters that are propagated along the trace through global variables and function calls.
Function models are combined into a high level model algorithm that can be used to restore or analyse it.
Nowadays it has become clear that no data store is all-purpose. SQL-based systems have been prevalent for several decades though this approach leads to serious issues in modern high scalability architectures. Thus, a number of different data stores have been designed to fulfill the needs of large-scale Web applications. Moreover, a single application often tends to use multiple data stores for different purposes and data. This paper covers common approaches to data persistence implementation and data store abstraction and also reveals basic considerations for design of a multi-store persistence layer for scalable Web applications. The paper consists of five sections. The first section (Introduction) discusses a problem of data management in the context of modern approaches to Web-applications design and development. The second section describes the most popular solutions of this problem based on traditional SQL-based DBMSs. Some limitations of these solutions are considered. The third section of the paper presents an overview of adventures and limitations of approached based on NoSQL DBMSs. A proposed novel approach of combine use SQL-based and NoSQL systems to develop and run Web-applications is a theme of the forth section. The final section concludes the paper.
One of the most important ways of increasing the speed of the modern databases is to cache frequently used data in RAM. Classical replacement policies are intended to minimize the number of buffer pool faults. This optimization method implicitly relies on the fact that the speeds of reading and writing to the hard disc are equal. Gradual technology improvement and cost reduction of flash memory have led to the creation of solid-state data storages (SSD) that are now increasingly used in personal computers and storage systems. Flash drives have advantages over traditional hard drives, high read and write speeds and significantly small time of random data access are the most important of them. However, the most popular flash-memory types read data at a higher speed than write it. Due to this feature the use of classical replacement algorithms of disk data caching is ineffective. This paper reviews recently developed algorithms of database buffer pool management designed to work with flash memory drives: CFDC (Clean First – Dirty Clustered), CASA (Cost-Aware Self-Adaptive), SAWC (Self Adaptive with Write Clustering), and FD-Buffer. Some of these algorithms demonstrate significant advantages over the classical algorithm LRU.
The presented overview is concerned with lexical query optimization and covers papers published in the last four decades. The paper consists of five sections. The first section – Introduction – classifies query optimization techniques into semantic optimizations and lexical optimizations. Semantic optimizations usually relies on data integrity rules that are stores within metadata part of databases, and on data statistics. This kind of optimizations is discussed in many textbooks and papers. Lexical optimizations (more often called rewriting) use only a text of query and no other information about database and its structure. Lexical optimizations are further classified into query transformations, query amelioration, and query reduction. The second section of the paper discusses techniques of query transformation such as predicate pushdown, transformation of nested query into query with joins, etc. Query amelioration is a topic of the third section with a focus on magic set optimizations. The forth section covers query reduction optimizations. The section briefly describes traditional approaches (such as tableau -based) are briefly described and considers in more details three new algorithms proposed by authors. The fifth section concludes the paper.
Linux driver verification is a large application area for software verification methods, in particular, for functional, safety, and security verification. Linux driver software is industrial production code — IT infrastructures rely on its stability, and thus, there are strong requirements for correctness and reliability. Linux driver software is complex, low-level systems code, and its characteristics make it necessary to bring to bear techniques from program analysis, SMT solvers, model checking, and other areas of software verification. These areas have recently made a significant progress in terms of precision and performance, and the complex task of verifying Linux driver software can be successful if the conceptual state-of-the-art becomes available in tool implementations.
The paper is based on experience of the research groups led by authors in verification of industrial software. It is important to develop verification tools that are efficient and effective enough to successfully check software components that are as complex as device drivers. In this area verifiers/researchers and Linux society find mutual benefits in cooperation because: for the society it is important to get such crucial software verified; for the verification community it is important to get realistic verification tasks in order to tune and further develop the technology. The paper provides an overview of the state-of-the-art and pointed out research directions in which further progress is essential. In particularly the paper considers most promising verification techniques and tools, including predicate abstraction, counter example generation, explicit-state verification, termination and concurrency analysis. One of main topic of Linux driver verification research is combination of verification techniques.
The paper investigates issues of Linux file system driver testing. Linux file system drivers are implemented as kernel modules, which works in the same address space as kernel core. For that reason, the driver should be very reliable. It should react adequately to incorrect file system images, to faults in operating system, etc. Also drivers should free all resources it requests as far as kernel have to work for long time without restart. Another important feature of file system drivers is that they are programs with multiple entry points, which may be executed simultaneously in respect with each other and with other kernel code.
Most of existing test systems verify only driver's behavior in normal situations by calling system calls, which are eventually dispatched by the kernel into the driver's functions. Some of them also check driver in concurrent scenarios but only at very basic level. Some test systems also verify driver's behavior under faulty environment, when request for memory allocation or disk read/write may fail. But fault scenarios used in those systems are probabilistic, which leads to problems with tests' reproducibility and requires to repeat tests many times to achieve better coverage. There is one test system, which checks for memory leaks in the driver under test.
The paper concludes by statement of requirements for more throughout file system driver testing. According to the requirements a test system have to cover the following aspects:
- Normal scenarios on system calls level.
- Parallel scenarios with additional checks for data races.
- Fault scenarios with insufficient memory and faulty block devices using such techniques as fault injection.
- Handling of incorrect file system images.
- Driver testing on system calls with invalid arguments.
- Check leaks of memory and other resources requested by driver under test.
ISSN 2220-6426 (Online)