bliftax 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3684c7584ac8b0997cf6de140dadf03327bea675
4
- data.tar.gz: 75bcb8953ee6979a0536f557326b7df0987eaa76
3
+ metadata.gz: 785167c0e657e38b987fd032dacacfeb2b31229e
4
+ data.tar.gz: 8144130dde9b34a98b76fb67d940cd81ee861d3d
5
5
  SHA512:
6
- metadata.gz: c4bd813c5b38f9ee2328f0e0bae284971a9ef88c1fe32d19a16c4d29644af8ce8287c576a3fa3e1a667f3f7c46d5ed544f2f7d64a1e934be520eb4dd6e93d2c9
7
- data.tar.gz: 581ec378e22f33b2e0bcaf804f9c3823d0d523094def03fd90f9c9872753ede88487cc45c0c7773a0d98080c433167636f6cfe8bcb813402784eafc4730bcd4c
6
+ metadata.gz: 769d3fea118d3ee1c2bac90fa5c727f7eb49f5c8ee2c68cc3e6ff3ec511491d47b1ede6b40ad4dbb988ac739cd8340dcdd677f1d4668b9b66e41b9e291d8c444
7
+ data.tar.gz: b804198d60ee236c8a3084a879fe6630acf38a319b8d6b9aa7b92563fcc825fe4f13209e20c307e46a316ce46266ccd4541afbd4d82f410e4878ad98df47c4f2
data/.travis.yml CHANGED
@@ -1,4 +1,13 @@
1
1
  language: ruby
2
+
2
3
  rvm:
3
4
  - 2.2.2
5
+
4
6
  before_install: gem install bundler -v 1.10.4
7
+
8
+ script: 'bundle exec rake'
9
+
10
+ notifications:
11
+ email:
12
+ on_failure: change
13
+ on_success: never
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Bliftax
2
2
 
3
+ [![Build Status](https://travis-ci.org/NigoroJr/bliftax.svg)](https://travis-ci.org/NigoroJr/bliftax)
4
+
3
5
  This is a simple library that parses a
4
6
  [BLIF](https://www.ece.cmu.edu/~ee760/760docs/blif.pdf) file and does
5
7
  operations used in logic optimization algorithms described in Chapter 4.10.2
@@ -29,6 +31,10 @@ This gem currently only supports the following declarations for BLIF:
29
31
 
30
32
  Following is the list of main features of this gem:
31
33
 
34
+ * 2-level logic optimization
35
+ - getting the prime implicants
36
+ - getting the essential prime implicants
37
+ - using branch heuristic
32
38
  * star operators
33
39
  * sharp operators
34
40
  * coverage check (b is covered by a)
@@ -37,6 +43,28 @@ Following is the list of main features of this gem:
37
43
 
38
44
  Here is an example usage of this gem.
39
45
 
46
+ ```ruby
47
+ #!/usr/bin/env ruby
48
+
49
+ require 'bliftax'
50
+
51
+ abort "Usage: #{$PROGRAM_NAME} <blif file>" if ARGV.empty?
52
+
53
+ BLIF_FILE = ARGV.first
54
+
55
+ model = Bliftax.new(BLIF_FILE)
56
+ output = model.dup
57
+
58
+ model.gates.each_with_index do |gate, i|
59
+ final_cover = Bliftax::Optimizer.optimize(gate)
60
+ output.gates[i].implicants = final_cover.to_a
61
+ end
62
+
63
+ puts output.to_blif
64
+ ```
65
+
66
+ Some other ways you can use this gem.
67
+
40
68
  ```ruby
41
69
  require 'bliftax'
42
70
 
@@ -98,6 +98,10 @@ class Bliftax
98
98
  # * C = NULL if A_i * B_i = NULL for more than one i
99
99
  # * Otherwise, C_i = A_i * B_i when A_i * B_i != NULL, and C_i = x (don't
100
100
  # care) for the coordinate where A_i * B_i = NULL
101
+ #
102
+ # @param rhs [Implicant] the right hand side of the operation.
103
+ #
104
+ # @return [Implicant] the result of the star operation.
101
105
  def star(rhs)
102
106
  # Sanity check
103
107
  unless @inputs.size == rhs.inputs.size
@@ -141,7 +145,7 @@ class Bliftax
141
145
  # * C = NULL if A_i # B_i = EPSILON for all i
142
146
  # * Otherwise, C = union of A_i = B_i' (negated) if A_i = x and B_i != x
143
147
  #
144
- # @param rhs [Implicant] the right hand side of the operation
148
+ # @param rhs [Implicant] the right hand side of the operation.
145
149
  #
146
150
  # @return [Set<Implicant>] Note that the set size could be 1.
147
151
  def sharp(rhs)
@@ -301,6 +305,23 @@ class Bliftax
301
305
  format '%s %s', @inputs.map(&:bit).join, @output.bit
302
306
  end
303
307
 
308
+ # Creates a dummy implicant with the given inputs.
309
+ # This is useful when checking if an implicant is equal to what is
310
+ # expected. The input labels are labeled from 'a' to 'z' then 'A' to 'Z',
311
+ # and the output label is 'out'.
312
+ #
313
+ # @param inputs [String, Array<String>] the input bits.
314
+ # @param output [String] the output bit.
315
+ #
316
+ # @return [Implicant] an implicant with dummy labels and the bits set to
317
+ # the given bits.
318
+ def self.make_dummy(inputs, output = '1')
319
+ labels = ('a'..'z').to_a + ('A'..'Z').to_a
320
+ in_labels = labels.first(inputs.size)
321
+ input_str = inputs.is_a?(Array) ? inputs.join : inputs
322
+ Implicant.new(in_labels, 'out', format('%s %s', input_str, output))
323
+ end
324
+
304
325
  # Creates a new NULL Implicant.
305
326
  #
306
327
  # @return [Implicant] a null Implicant
@@ -0,0 +1,202 @@
1
+ class Bliftax
2
+ # A module that does 2-level logic optimization
3
+ module Optimizer
4
+ module_function
5
+
6
+ # Does 2-level logic optimization to the given gate (a set of implicants).
7
+ # This is done in the following steps (as described in the book
8
+ # Fundamentals of Digital Logic with Verilog Design.
9
+ #
10
+ # 1. Find all prime implicants by using the star operator until the
11
+ # resulting set of implicants is the same as the previous round.
12
+ # 2. Apply the sharp operation to one of the prime implicants against all
13
+ # other implicants. The operation is cascaded. If the result is not
14
+ # null, it is an essential prime implicant. Do this for all prime
15
+ # implicants.
16
+ # 3. For the non-essential prime implicants, remove the ones that can be
17
+ # covered by some other implicant but with less cost.
18
+ # 4. For the remaining implicants, use the branching heuristic to find the
19
+ # set of prime implicants with the minimum cost.
20
+ #
21
+ # @param gate [Bliftax::Gate, Set<Implicant>, Array<Implicant>] the set of
22
+ # implicants to be optimized.
23
+ #
24
+ # @return [Set<Implicant>] the resulting optimized set of implicants that
25
+ # covers the same minterms.
26
+ def optimize(gate)
27
+ implicants = gate.is_a?(Bliftax::Gate) ? gate.implicants : gate
28
+ primes = get_prime_implicants(implicants)
29
+
30
+ essentials = get_essential_implicants(primes)
31
+
32
+ # Essential implicants will always be essential
33
+ primes -= essentials
34
+
35
+ # Find minterms that still needs to be covered
36
+ need_cover = implicants.map(&:minterms).to_set.flatten
37
+ need_cover -= essentials.map(&:minterms).to_set.flatten
38
+
39
+ # Remove implicants with higher cost
40
+ primes.to_a.permutation(2).each do |a, b|
41
+ # If b has same coverage but cheaper
42
+ if a.cost > b.cost && (a.minterms & need_cover) <= b.minterms
43
+ primes.delete(a)
44
+ end
45
+ end
46
+
47
+ # Branching heuristic
48
+ to_use = branching(need_cover, primes)
49
+
50
+ essentials.union(to_use)
51
+ end
52
+
53
+ # Returns the prime implicants of the given set of implicants.
54
+ # This method successively applies the star operations to the given
55
+ # implicants to find the prime implicants.
56
+ #
57
+ # @param implicants [Set<Implicant>, Array<Implicant>] the original set of
58
+ # implicants.
59
+ #
60
+ # @return [Set<Implicant>] a set of prime implicants.
61
+ def get_prime_implicants(implicants)
62
+ # Use star operator to find prime implicants
63
+ star_set = Set.new(implicants)
64
+ prev_set = Set.new
65
+
66
+ loop do
67
+ prev_set = star_set.dup
68
+ prev_set.to_a.combination(2).each do |a, b|
69
+ result = a * b
70
+ star_set.add(result) unless result.null?
71
+ end
72
+
73
+ # Remove redundant implicants
74
+ union = star_set.union(prev_set)
75
+ union.to_a.permutation(2).each do |a, b|
76
+ star_set.delete(b) if a.covers?(b)
77
+ end
78
+
79
+ break if star_set == prev_set
80
+ end
81
+
82
+ star_set
83
+ end
84
+
85
+ # Finds the essential implicants of the given set of implicants.
86
+ # This method applies the sharp operation to an implicant against each of
87
+ # the other implicants in the set, and adds the tested implicant if and
88
+ # only if the result of the cascaded sharp operation is not null.
89
+ #
90
+ # @param implicants [Set<Implicant>, Array<Implicant>] the original set of
91
+ # implicants.
92
+ #
93
+ # @return [Set<Implicant>] the essential implicants of the given set of
94
+ # implicants.
95
+ def get_essential_implicants(implicants)
96
+ sharp_set = Set.new
97
+
98
+ implicants.each do |a|
99
+ result_set = Set.new([a])
100
+
101
+ implicants.each do |b|
102
+ next if b == a
103
+
104
+ copy = result_set.dup
105
+ result_set.clear
106
+ copy.each do |new_a|
107
+ result_set.add(new_a.sharp(b))
108
+ end
109
+ result_set.flatten!
110
+ result_set.delete_if { |s| s.null? }
111
+ end
112
+
113
+ sharp_set.add(a) unless result_set.empty?
114
+ end
115
+
116
+ sharp_set
117
+ end
118
+
119
+ # Cost heuristic.
120
+ # If an Implicant is given, the cost of that Implicant is returned.
121
+ # Otherwise, the sum of the number of implicants and the cost of each
122
+ # implicant is returned as the cost for that collection.
123
+ #
124
+ # @param what [Implicant, #to_a<#cost>] the thing to be evaluated.
125
+ #
126
+ # @return the evaluated cost
127
+ def cost(what)
128
+ return what.cost if what.is_a?(Bliftax::Implicant)
129
+
130
+ cost_sum = what.size
131
+ cost_sum += what.to_a.reduce(0) { |a, e| a + e.cost }
132
+ cost_sum
133
+ end
134
+
135
+ # Finds the minimum-cost combination to cover the given minterms.
136
+ # This method does recursive DFS to search for the minimum-cost
137
+ # combination, so it may become slow depending on the number of available
138
+ # options.
139
+ #
140
+ # @param to_cover [Set<Integer>] the set of minterms that need to be
141
+ # covered.
142
+ # @param options [Set<Implicant>] the set of implicants to choose from.
143
+ def branching(to_cover, options)
144
+ to_use = Set.new
145
+ options.dup.each do |implicant|
146
+ result = branching_helper(to_cover, options, implicant)
147
+ if result.include?(implicant)
148
+ to_use.add(implicant)
149
+ to_cover -= implicant.minterms
150
+ options.delete(implicant)
151
+ end
152
+ end
153
+ to_use
154
+ end
155
+
156
+ private
157
+
158
+ module_function
159
+
160
+ # A helper method for the recursive DFS for branching heuristic.
161
+ #
162
+ # @param to_cover [Set<Integer>] minterms that need to be covered.
163
+ # @param options [Set<Implicant>] the prime implicants that we can choose
164
+ # from.
165
+ # @param implicant [Implicant] the implicant that's being decided whether
166
+ # to include in the final cover or not.
167
+ # @return the set that results in a better cost when including or not
168
+ # including the implicant.
169
+ def branching_helper(to_cover, options, implicant)
170
+ # Get implicants from options that cover at least one required vertex
171
+ options = options.select do |o|
172
+ !(to_cover & o.minterms).empty?
173
+ end
174
+ options = options.to_set
175
+
176
+ # Base case
177
+ return Set.new if options.empty?
178
+
179
+ # Final cover when using the implicant
180
+ new_options = options - Set.new([implicant])
181
+ using_implicant = branching_helper(to_cover - implicant.minterms,
182
+ new_options,
183
+ new_options.to_a.first)
184
+ # Don't forget to add this implicant
185
+ using_implicant.add(implicant)
186
+ # Final cover when not using the implicant
187
+ not_using_implicant = branching_helper(to_cover,
188
+ new_options,
189
+ new_options.to_a.first)
190
+
191
+ cost_using = cost(using_implicant)
192
+ cost_not_using = cost(not_using_implicant)
193
+
194
+ # Not using this implicant results in as good a coverage but less cost
195
+ minterms_coverage = not_using_implicant.map(&:minterms).to_set.flatten
196
+ if cost_not_using < cost_using && minterms_coverage >= to_cover
197
+ return not_using_implicant
198
+ end
199
+ return using_implicant
200
+ end
201
+ end
202
+ end
@@ -1,3 +1,3 @@
1
1
  class Bliftax
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/bliftax.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'bliftax/gate'
2
2
  require 'bliftax/implicant'
3
+ require 'bliftax/optimizer'
3
4
  require 'bliftax/version'
4
5
 
5
6
  # A class that parses a BLIF file.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bliftax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naoki Mizuno
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-16 00:00:00.000000000 Z
11
+ date: 2015-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,6 +73,7 @@ files:
73
73
  - lib/bliftax/gate.rb
74
74
  - lib/bliftax/implicant.rb
75
75
  - lib/bliftax/implicant/bit.rb
76
+ - lib/bliftax/optimizer.rb
76
77
  - lib/bliftax/version.rb
77
78
  homepage: https://github.com/NigoroJr/bliftax
78
79
  licenses: