Addition/Substraction Optimization in Yosys - synthesis

I have the following very simple verilog module, which depending on the input op either performs a+b or a-b.
module addsub (a, b, op, r);
parameter DATA_WIDTH = 4;
input [DATA_WIDTH-1:0] a, b;
input op;
output [DATA_WIDTH-1:0] r;
assign r = op ? a-b : a+b;
endmodule
Now when I synthesize this code using yosys (version 0.9, script below) I get two $alu modules, both fed by the inputs a and b, where one has its CI and BI inputs asserted. The output r is generated using a mutliplexer.
read_verilog addsub.v
synth -flatten -run begin:fine
#share -aggressive; opt
show
However, I would like to get yosys the recognize that only one $alu is necessary, where the CI and BI inputs are connected to op. Hence, I tried the share command (commented out in the script above) and indeed the two $alus are merged into one, but now I get a strange (redundant) multiplexer structure at the inputs a and b see here.
My question is what am I doing wrong, is there a special pass to get rid of these multiplexers, or am I completely on the wrong track here?
Solution as suggested by David Shah:
The yosys version I had installed did not feature the opt_share command. Hence, I compiled the current version (0.9+3558) and now the following synthesis script works as expected:
read_verilog addsub.v
synth -flatten -run begin:fine
share -aggressive; opt
opt_share; opt
show

The pass you are looking for is opt_share, but it might be newer than the 0.9 release in which case you will need Yosys from git master.

Related

How can I map frama-c CLI code to the original c statement? And how can I find the documentation of the api of the frama-c?

I'm trying to get the program dependence graph (PDG) using frama-c at the original code's statement level. However, 'pdg' plug-in in frama-c prints the PDG at the parsed code's node level.
Since frama-c-gui can highlight the original statement corresponds to the node in the parsed code, I'm pretty sure that there is a mapping between the node in parsed code and the original code's statement. How can I get this mapping? Just the line number at the original code is fine, too.
Frama-C's GUI presents two views of the code:
The CIL code (C Intermediate Language), often called normalized source code, which corresponds to a pretty-printing of Frama's AST, in the top center panel;
And the original source code, on the top right panel.
I'm assuming that by parsed code you are talking about the CIL (normalized) code.
Every element in Frama-C's AST contains a location, which is a pair of positions: the first and last coordinates (line, row, column) in the original code which correspond to that element (minus a few exceptions, such as generated elements, macro expansions, etc). Most AST elements have ways to retrieve that location.
In the case of PDG nodes, you can get the associated statements (if any) and then print their location, as in the code below (run with frama-c -pdg -load-module print_pdg.ml <file>):
(* print_pdg.ml *)
let () = Db.Main.extend (fun () ->
Globals.Functions.iter (fun kf ->
let pdg = !Db.Pdg.get kf in
!Db.Pdg.iter_nodes (fun n ->
match PdgTypes.Node.stmt n with
| None -> ()
| Some st ->
Format.printf "%a: %a#."
Printer.pp_location (Cil_datatype.Stmt.loc st) Printer.pp_stmt st
) pdg
)
)
Note that my example script will print each statement multiple times, if there are multiple PDG nodes associated to the same statement.
By default, Printer.pp_location only prints the file name and line of the starting character, but you can make a custom pretty-printer to include the column as well, or the coordinates of the last character.
API and Plug-in Documentation (from question in comment)
Some Frama-C plug-ins (Eva, WP, E-ACSL, etc.) have their own manuals, which are available in the Frama-C download page.
There is no specific manual for the Pdg plug-in, but some Ocamldoc-generated HTML pages can be obtained from the Frama-C API archive.
However, what most Frama-C plug-in developers prefer is to use the OCaml Merlin plug-in in their favorite editor (emacs, vim, etc) to navigate the code and read the source comments (in the .mli files, for instance).
On Emacs, for instance, C-c C-l on a module/variable name jumps to its definition, and C-c C-a alternates between .ml and .mli files (implementation - documentation). Combined with auto-completion for module/function discovery, this provides a form of interactive documentation that many OCaml developers are comfortable with.

Performing dead code elimination / slicing from original source code in Frama-C

EDIT: The original question had unnecessary details
I have a source file which I do value analysis in Frama-C, some of the code is highlighted as dead code in the normalized window, no the original source code.
Can I obtain a slice of the original code that removes the dead code?
Short answer: there's nothing in the current Frama-C version that will let you do that directly. Moreover, if your original code contains macros, Frama-C will not even see the real original code, as it relies on an external preprocessor (e.g. cpp) to do macro expansion.
Longer answer: Each statement in the normalized (aka CIL) Abstract Syntax Tree (AST, the internal representation of C code within Frama-C) contains information about the location (start point and end point) of the original statement where it stems from, and this information is also available in the original AST (aka Cabs). It might thus be possible for someone with a good knowledge of Frama-C's inner workings (e.g. a reader of the developer's manual), to build a correspondance between both, and to use that to detect dead statement in Cabs. Going even further, one could bypass Cabs, and identify zones in the original text of the program which are dead code. Note however that it would be a tedious and quite error prone (notably because a single original statement can be expanded in several normalized ones) task.
Given your clarifications, I stand by #Virgile's answer; but for people interested in performing some simplistic dead code elimination within Frama-C, the script below, gifted by a colleague who has no SO account, could be helpful.
(* remove_dead_code.ml *)
let main () =
!Db.Value.compute ();
Slicing.Api.Project.reset_slicing ();
let selection = ref Slicing.Api.Select.empty_selects in
let o = object (self)
inherit Visitor.frama_c_inplace
method !vstmt_aux stmt =
if Db.Value.is_reachable_stmt stmt then
selection :=
Slicing.Api.Select.select_stmt ~spare:true
!selection
stmt
(Extlib.the self#current_kf);
Cil.DoChildren
end in
Visitor.visitFramacFileSameGlobals o (Ast.get ());
Slicing.Api.Request.add_persistent_selection !selection;
Slicing.Api.Request.apply_all_internal ();
Slicing.Api.Slice.remove_uncalled ();
ignore (Slicing.Api.Project.extract "no-dead")
let () = Db.Main.extend main
Usage:
frama-c -load-script remove_dead_code.ml file.c -then-last -print -ocode output.c
Note that this script does not work in all cases and could have further improvements (e.g. to handle initializers), but for some quick-and-dirty hacking, it can still be helpful.

What is the rule behind instruction count in Intel PIN?

I wanted to count instructions in simple recursive fibo function O(2^n). I succeded to do so with bubble sort and matrix multiplication, but in this case it seemed like instruction count ignored my fibo function. Here is the code used for instrumentation:
// Insert a call at the entry point of a routine to increment the call count
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_rtnCount), IARG_END);
// For each instruction of the routine
for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
{
// Insert a call to docount to increment the instruction counter for this rtn
INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_icount), IARG_END);
}
I started to wonder what's the difference between this program and the previous ones and my first thought was: here I'm not using an array.
This is what I realised after some manual tests:
a = 5; // instruction ignored by PIN and
// pretty much everything not using array
fibo[1] = 1 // instruction counted properly
a = fibo[1] // instruction ignored by PIN
So it seems like only instructions counted are writes to the memory (that's what I assume). After I changed my fibo function to this it works:
long fibonacciNumber(int n, long *fiboNumbers)
{
if (n < 2) {
fiboNumbers[n] = n;
return n;
}
fiboNumbers[n] = fiboNumbers[n-1] + fiboNumbers[n-2];
return fibonacciNumber(n - 1, fiboNumbers) + fibonacciNumber(n - 2, fiboNumbers);
}
But I would like to count instructions also for programs that aren't written by me. Is there a way to count all type of instrunctions? Is there any particular reason why only this instructions are counted? Any help appreciated.
//Edit
I used disassembly option in Visual Studio to check how it looks and it still makes no sense for me. I can't find the reason why only assingment to array is interpreted by PIN as instruction.
instruction_comparison
This exceeded all my expectations, counted as 2 instructions:
even 2 instructions, not one
PIN, like other low-level profiling and analysis tools, measures individual instructions, low-level orders like "add these two registers" or "load a value from that memory address". The sequence of instructions which a program comprises are generally produced from a high-level language like C++ through a compiler. An individual line of C++ code might be transformed into exactly one instruction, but it's also common for a line to translate to several instructions or even to zero instructions; and the instructions for a line of code may be interleaved with those of other instructions.
Your compiler can output an assembly-language file for your source code, showing what instructions were produced for which lines of code. (For GCC and Clang, this is done with the -S flag.) Note that reading the assembly code output from a compiler is not the best way to learn assembly. Also, I would point you to godbolt.org, a very convenient tool for analyzing assembly output.

Using Impact analysis in Frama-C

I tried using frama-c-gui and was able to perform impact analysis
But I am not able to figure out how can we pass statment number on which the impact analysis needs to be performed in batch mode of Frama-C.
There is a special annotation //# impact pragma stmt; that you can use to indicate that you are interested in the impact of the statement following the annotation. Then, if said annotation is in function f, you can use the following command line to print the impacted code on the command line:
frama-c -impact-pragma f -impact-slicing impact.c -then-on "impact slicing" -print
-impact-pragma f indicates that you are interested by the statements flagged by a pragma in function f
-impact-slicing indicates that you want to create a project named impact slicing containing the statements impacted by the one(s) you have selected.
-then-on "impact-slicing" let you continue the analysis on project impact slicing (here we only -print the code, but you can put any option you like after -then-on project_name)
Note however that the impact plugin is quite experimental.

Matlab: Attempt to reference field of non-structure array

I am using the Kernel Density Estimator toolbox form http://www.ics.uci.edu/~ihler/code/kde.html . But I am getting the following error when I try to execute the demo files -
>> demo_kde_3
KDE Example #3 : Product sampling methods (single, anecdotal run)
Attempt to reference field of non-structure array.
Error in double (line 10)
if (npd.N > 0) d = 1; % return 1 if the density exists
Error in repmat (line 49)
nelems = prod(double(siz));
Error in kde (line 39)
if (size(ks,1) == 1) ks = repmat(ks,[size(points,1),1]); end;
Error in demo_kde_3 (line 8)
p = kde([.1,.45,.55,.8],.05); % create a mixture of 4 gaussians for
testing
Can anyone suggest what might be wrong? I am new to Matlab and having a hard time to figure out the problem.
Thank You,
Try changing your current directory away from the #kde folder; you may have to add the #kde folder to your path when you do this. For example run:
cd('c:\');
addpath('full\path\to\the\folder\#kde');
You may also need to add
addpath('full\path\to\the\folder\#kde\examples');
Then see if it works.
It looks like function repmat (a mathworks function) is picking up the #kde class's version of the double function, causing an error. Usually, only objects of the class #kde can invoke that functions which are in the #kde folder.
I rarely use the #folder form of class definitions, so I'm not completely sure of the semantics; I'm curious if this has any effect on the error.
In general, I would not recommend using the #folder class format for any development that you do. The mathworks overhauled their OO paradigm a few versions ago to a much more familiar (and useful) format. Use help classdef to see more. This #kde code seems to predate this upgrade.
MATLAB gives you the code line where the error occurs. As double and repmat belong to MATLAB, the bug probably is in kde.m line 39. Open that file in MATLAB debugger, set a breakpoint on that line (so the execution stops immediately before the execution of that specific line), and then when the code is stopped there, check the situation. Try the entire code line in console (copy-paste or type it, do not single-step, as causing an uncatched error while single-stepping ends the execution of code in debugger), it should give you an error (but doesn't stop execution). Then try pieces of the code of that code line, what works as it should and what not, eg. does the result of size(points, 1) make any sense.
However, debugging unfamiliar code is not an easy task, especially if you're a beginner in MATLAB. But if you learn and understand the essential datatypes of MATLAB (arrays, cell arrays and structs) and the different ways they can be addressed, and apply that knowledge to the situation on the line 39 of kde.m, hopefully you can fix the bug.
Repmat calls double and expects the built-in double to be called.
However I would guess that this is not part of that code:
if (npd.N > 0) d = 1; % return 1 if the density exists
So if all is correct this means that the buil-tin function double has been overloaded, and that this is the reason why the code crashes.
EDIT:
I see that #Pursuit has already addressed the issue but I will leave my answer in place as it describes the method of detection a bit more.

Resources