Module: ABC
- Defined in:
- ext/ruby_abc/ruby_abc.c,
lib/ruby_abc.rb,
lib/ruby_abc/version.rb,
ext/ruby_abc/ruby_abc.c
Overview
This module wrapps the command line interface of the Berkeley ABC program. ABC is a system for sequential synthesis and verification, developped at the University of California, Berkeley. Documentation on ABC can be found at http://people.eecs.berkeley.edu/~alanmi/abc/
The ABC program is a command line interface: the user issues commands and adjust them according to the results he gets back. In order to automate this process, the ABC module allows to retreive some information on the logic network in ruby, such as the number of nodes or its logic level. The command adjustment can then be done in ruby instead of manually.
ABC commands are issued with the run_command module function, thus the ABC documentation is not covered in this API documentation.
However, available commands can be retreived with ABC.run_command('help')',
and the documentation of a given command can be retreived with
ABC.run_command('command_name -h')`.
Constant Summary collapse
- VERSION =
This gem version
'0.1.0'
Class Method Summary collapse
-
.echo_commands ⇒ Boolean
Return if each command sent to ABC is to be echoed back.
-
.echo_commands=(b) ⇒ Object
Set whether each command sent to ABC is to be echoed back or not.
-
.map(k, area: false, verbose: true) ⇒ Integer
Map the logic network to nodes with at most lut_size inputs.
-
.method_missing(name, *args) ⇒ Object
Send missing methods to ABC as commands.
-
.nb_ands ⇒ Integer?
Returns the number of AND-inverter gates in the network.
-
.nb_latches ⇒ Integer?
Returns the number of latches in the network.
-
.nb_levels ⇒ Integer?
Returns the number of logic levels.
-
.nb_nodes ⇒ Integer?
Returns the number combinatorial logic nodes in the network.
-
.nb_primary_inputs ⇒ Integer?
Returns the number of primary inputs of the network.
-
.nb_primary_outputs ⇒ Integer?
Returns the number of primary outputs of the network.
-
.optimize(verbose: true) ⇒ Integer
Combinatorial synthesis of the network.
-
.print_stats ⇒ nil
Print out network statistics.
-
.run_command(cmd) ⇒ Boolean
Run the command string in ABC.
-
.synthesis(input: nil, output: nil, zero: false, sweep: false, retime: false, lcorr: false, area: false, lut_map: nil, verbose: true, gatelib: false) ⇒ nil
This method is an atempt to automate the logic synthesis process (combinatorial and sequential) according to some parameters.
Class Method Details
.echo_commands ⇒ Boolean
Return if each command sent to ABC is to be echoed back.
136 137 138 139 140 141 |
# File 'ext/ruby_abc/ruby_abc.c', line 136
static VALUE rubyabc_get_echo_commands(VALUE self)
{
if (rubyabc_echo_commands)
return Qtrue;
return Qfalse;
}
|
.echo_commands=(b) ⇒ Object
Set whether each command sent to ABC is to be echoed back or not.
148 149 150 151 152 153 154 155 156 |
# File 'ext/ruby_abc/ruby_abc.c', line 148
static VALUE rubyabc_set_echo_commands(VALUE self, VALUE b)
{
if (b == Qfalse || b == Qnil)
rubyabc_echo_commands = 0;
else
rubyabc_echo_commands = 1;
return Qnil;
}
|
.map(k, area: false, verbose: true) ⇒ Integer
Map the logic network to nodes with at most lut_size inputs. If area is true, minimize the number of nodes instead of minimizing the logic level of the network.
This method loops the command: choice2; if -K #{lut_size}#{optimize_for_area ? ' -a' : ''}; ps
and stops when the number of nodes stop decreasing.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/ruby_abc.rb', line 87 def self.map(k, area: false, verbose: true) map_cmd = "choice2; if -K #{k}#{area ? ' -a' : ''}#{verbose ? '; ps' : ''}" min_n_nodes = Float::INFINITY loop do ABC::run_command(map_cmd) n_nodes = ABC::nb_nodes break if n_nodes >= min_n_nodes min_n_nodes = [min_n_nodes, n_nodes].min end if ABC::nb_nodes > min_n_nodes then 5.times do ABC::run_command(map_cmd) break if ABC::nb_nodes <= min_n_nodes end end return ABC::nb_nodes end |
.method_missing(name, *args) ⇒ Object
Send missing methods to ABC as commands.
The method_missing method is implemented so that commands can be issued to abc without using ABC::run_command. Methods arguments are concatenated as strings to the command.
116 117 118 119 120 |
# File 'lib/ruby_abc.rb', line 116 def self.method_missing (name, *args) cmd = name.to_s cmd += ' ' + args.join(' ') if args ABC::run_command cmd end |
.nb_ands ⇒ Integer?
Returns the number of AND-inverter gates in the network. If no network have been loaded or the then network is not in AIG form, returns nil.
12 13 14 15 16 17 18 19 20 |
# File 'ext/ruby_abc/ruby_abc.c', line 12
static VALUE rubyabc_n_ands(VALUE self)
{
int res = rubyabc_c_n_ands();
if (res < 0)
return Qnil;
return INT2NUM(res);
}
|
.nb_latches ⇒ Integer?
Returns the number of latches in the network. If no network have been loaded, return nil.
72 73 74 75 76 77 78 79 80 |
# File 'ext/ruby_abc/ruby_abc.c', line 72
static VALUE rubyabc_n_latches(VALUE self)
{
int res = rubyabc_c_n_latches();
if (res < 0)
return Qnil;
return INT2NUM(res);
}
|
.nb_levels ⇒ Integer?
Returns the number of logic levels. This is the number of combinatorial logic between two latches or primary input/output. If no network have been loaded, return nil.
89 90 91 92 93 94 95 96 97 |
# File 'ext/ruby_abc/ruby_abc.c', line 89
static VALUE rubyabc_n_levels(VALUE self)
{
int res = rubyabc_c_n_levels();
if (res < 0)
return Qnil;
return INT2NUM(res);
}
|
.nb_nodes ⇒ Integer?
Returns the number combinatorial logic nodes in the network. If no network have been loaded or the then network is in AIG form, returns nil.
27 28 29 30 31 32 33 34 35 |
# File 'ext/ruby_abc/ruby_abc.c', line 27
static VALUE rubyabc_n_nodes(VALUE self)
{
int res = rubyabc_c_n_nodes();
if (res < 0)
return Qnil;
return INT2NUM(res);
}
|
.nb_primary_inputs ⇒ Integer?
Returns the number of primary inputs of the network. If no network have been loaded, return nil.
42 43 44 45 46 47 48 49 50 |
# File 'ext/ruby_abc/ruby_abc.c', line 42
static VALUE rubyabc_n_pis(VALUE self)
{
int res = rubyabc_c_n_pis();
if (res < 0)
return Qnil;
return INT2NUM(res);
}
|
.nb_primary_outputs ⇒ Integer?
Returns the number of primary outputs of the network. If no network have been loaded, return nil.
57 58 59 60 61 62 63 64 65 |
# File 'ext/ruby_abc/ruby_abc.c', line 57
static VALUE rubyabc_n_pos(VALUE self)
{
int res = rubyabc_c_n_pos();
if (res < 0)
return Qnil;
return INT2NUM(res);
}
|
.optimize(verbose: true) ⇒ Integer
Combinatorial synthesis of the network.
This method loops the command "resyn; resyn2, resyn3, print_stats" and stops when the number of AND gates stop decreasing. At the end, the logic network is in AIG form.
"Fast and efficient synthesis is achieved by DAG-aware rewriting of the AIG. Rewriting is performed using a library of pre-computed four-input AIGs (command rewrite; standard alias rw), or collapsing and refactoring of logic cones with 10-20 inputs (command refactor; standard alias rf). It can be experimentally shown that iterating these two transformations and interleaving them with AIG balancing (command balance; standard alias b) substantially reduces the AIG size and tends to reduce the number of AIG levels."
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/ruby_abc.rb', line 56 def self.optimize(verbose: true) cmd = 'resyn; resyn2; resyn3' + (verbose ? '; ps' : '') min_n_ands = Float::INFINITY loop do ABC::run_command(cmd) n_ands = ABC::nb_ands break if n_ands >= min_n_ands min_n_ands = [min_n_ands, n_ands].min end if ABC::nb_ands > min_n_ands then 5.times do ABC::run_command(cmd) break if ABC::nb_ands <= min_n_ands end end return ABC::nb_ands end |
.print_stats ⇒ nil
Print out network statistics.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/ruby_abc.rb', line 18 def self.print_stats n_pis = ABC::nb_primary_inputs n_pos = ABC::nb_primary_outputs n_nodes = ABC::nb_nodes n_latches = ABC::nb_latches n_levels = ABC::nb_levels n_ands = ABC::nb_ands arr = [n_pis, n_pos, n_nodes, n_latches, n_levels, n_ands].reject{|v| v.nil?} return nil if arr.empty? max_len = arr.collect{|v| v.to_s.length}.max + 1 puts "Inputs: ...#{(' ' + n_pis.to_s).rjust(max_len, '.')}" if n_pis puts "Outputs: ..#{(' ' + n_pos.to_s).rjust(max_len, '.')}" if n_pos puts "Nodes: ....#{(' ' + n_nodes.to_s).rjust(max_len, '.')}" if n_nodes puts "Latches: ..#{(' ' + n_latches.to_s).rjust(max_len, '.')}" if n_latches puts "And gates: #{(' ' + n_ands.to_s).rjust(max_len, '.')}" if n_ands puts "Levels: ...#{(' ' + n_levels.to_s).rjust(max_len, '.')}" if n_levels return nil end |
.run_command(cmd) ⇒ Boolean
Run the command string in ABC.
If ABC::echo_commands has been set to true, string will be echoed on STDOUT before it is given to ABC.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'ext/ruby_abc/ruby_abc.c', line 114
static VALUE rubyabc_run_command(VALUE self, VALUE cmd)
{
VALUE printed_str;
Check_Type(cmd, T_STRING);
if (rubyabc_echo_commands) {
printed_str = rb_sprintf("Command: \"%"PRIsVALUE"\"", cmd);
rb_io_puts(1, &printed_str, rb_stdout);
}
if (rubyabc_c_run_command(StringValueCStr(cmd)))
return Qfalse;
return Qtrue;
}
|
.synthesis(input: nil, output: nil, zero: false, sweep: false, retime: false, lcorr: false, area: false, lut_map: nil, verbose: true, gatelib: false) ⇒ nil
This method is an atempt to automate the logic synthesis process (combinatorial and sequential) according to some parameters.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/ruby_abc.rb', line 137 def self.synthesis(input: nil, output: nil, zero: false, sweep: false, retime: false, lcorr: false, area: false, lut_map: nil, verbose: true, gatelib: false) if input then raise "Expecting a string for :input argument" unless input.kind_of?(String) ABC::read input end puts "---- Input netlist ----" ABC::print_stats puts "-----------------------" ABC::ps if verbose if sweep then ABC::sweep ABC::ps end if zero and ABC::nb_latches > 0 then ABC::run_command 'strash; zero' else ABC::run_command 'strash' end ABC::ps if verbose ABC::lcorr if (lcorr and ABC::nb_latches > 0) if sweep then ABC::ssweep ABC::csweep ABC::ps if verbose end ABC::optimize(verbose: verbose) if retime and ABC::nb_latches > 0 then level = ABC::nb_levels ABC::run_command('retime; strash') ABC::ps if verbose if ABC::nb_levels >= level then ABC::run_command('dretime; strash') ABC::ps if verbose end ABC::optimize(verbose: verbose) end ABC::zero if zero if lut_map then raise "Expecting a strictly positive integer for argument :lut_map" unless (lut_map.kind_of?(Integer) and lut_map > 0) ABC::map(lut_map, area: not(not(area)), verbose: verbose) end if sweep then ABC::run_command 'sop; sweep; resyn; resyn2; resyn3; scleanup; resyn; scleanup; scleanup; scleanup; strash; ssweep; csweep' ABC::ps if verbose ABC::optimize(verbose: verbose) if lut_map then raise "Expecting a strictly positive integer for argument :lut_map" unless (lut_map.kind_of?(Integer) and lut_map > 0) ABC::map(lut_map, area: not(not(area)), verbose: verbose) end end if (lcorr and ABC::nb_latches > 0) then ABC::run_command 'strash; lcorr' if lut_map then raise "Expecting a strictly positive integer for argument :lut_map" unless (lut_map.kind_of?(Integer) and lut_map > 0) ABC::map(lut_map, area: not(not(area)), verbose: verbose) end end if gatelib then gatelib = case gatelib when 'osu', true File.('../../share/osu018.genlib', __FILE__) when 'simple' File.('../../share/simple.genlib', __FILE__) when String gatelib = File.absolute_path(gatelib) end abort "ERROR: File \"#{gatelib}\" does not exist!" unless File.file?(gatelib) ABC::run_command("read_genlib#{verbose ? '' : ' -v'} '#{gatelib}'") ABC::run_command("print_genlib") if verbose map_cmd = "choice2; map#{area ? ' -a' : ''}#{sweep ? ' -s' : ''}#{verbose ? '; ps' : ''}" min_n_nodes = Float::INFINITY loop do ABC::run_command(map_cmd) n_nodes = ABC::nb_nodes break if n_nodes >= min_n_nodes min_n_nodes = [min_n_nodes, n_nodes].min end if ABC::nb_nodes > min_n_nodes then 5.times do ABC::run_command(map_cmd) break if ABC::nb_nodes <= min_n_nodes end end ABC::run_command("print_gates") if verbose end puts "---- output netlist ----" ABC::print_stats puts "------------------------" if output then raise "Expecting a string for :output argument" unless output.kind_of?(String) puts "Writing output netlist to file \"#{output}\"" if input then ABC.write_hie input, output else ABC.write output end end nil end |