Class: ArtDecomp::FSM
- Inherits:
-
Object
- Object
- ArtDecomp::FSM
- Defined in:
- lib/art-decomp/fsm.rb
Instance Attribute Summary collapse
-
#codes ⇒ Object
readonly
Returns the value of attribute codes.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
- #beta_f ⇒ Object
- #beta_q ⇒ Object
- #beta_qp ⇒ Object
- #beta_x(ins) ⇒ Object
- #beta_y(ins) ⇒ Object
- #expand_x(ins) ⇒ Object
- #fsm_cells(archs) ⇒ Object
- #general_relevance ⇒ Object
- #hash ⇒ Object
- #implementable_in?(archs) ⇒ Boolean
-
#initialize(inputs, outputs, state, next_state, codes = {}) ⇒ FSM
constructor
A new instance of FSM.
- #input_count ⇒ Object
- #output_count ⇒ Object
- #q_encoding(rows) ⇒ Object
- #state_rows_of_next_state_of(rows) ⇒ Object
- #stats ⇒ Object
- #structure ⇒ Object
- #to_kiss ⇒ Object
- #to_vhdl(name) ⇒ Object
- #truth_table? ⇒ Boolean
- #unique_relevance ⇒ Object
- #x_encoding(ins, rows) ⇒ Object
- #y_encoding(rows) ⇒ Object
Constructor Details
#initialize(inputs, outputs, state, next_state, codes = {}) ⇒ FSM
Returns a new instance of FSM.
41 42 43 |
# File 'lib/art-decomp/fsm.rb', line 41 def initialize inputs, outputs, state, next_state, codes = {} @inputs, @outputs, @state, @next_state, @codes = inputs.freeze, outputs.freeze, state.freeze, next_state.freeze, codes.freeze end |
Instance Attribute Details
#codes ⇒ Object (readonly)
Returns the value of attribute codes.
3 4 5 |
# File 'lib/art-decomp/fsm.rb', line 3 def codes @codes end |
Class Method Details
.from_kiss(kiss) ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/art-decomp/fsm.rb', line 5 def self.from_kiss kiss kiss = File.read kiss unless kiss.index "\n" inputs, outputs, state, next_state = [], [], [], [] codes = Hash[kiss.lines.grep(/^\.code [^*]/).map(&:split).map { |_, state, code| [state.to_sym, code.to_sym] }] codes = Hash[kiss.lines.grep(/^# States\./).map(&:split).map { |_, state, code| [state[7..-1].to_sym, code.to_sym] }] if codes.empty? kiss.lines do |line| case line when /^\s*[01-]+\s+\S+\s+\S+\s+[01-]+\s*$/ then ins, st, nxt, outs = *line.split when /^\s*[01-]+\s+[01-]+\s*$/ then st, nxt, ins, outs = DontCare, DontCare, *line.split when /^\.end_kiss$/ then break else next end next if [DontCare, '*'].include? nxt and outs =~ /^-*$/ if line =~ /^[01-]+\s+[01-]+$/ and not codes.empty? size = codes.values.first.size st = ins[-size..-1] == '-' * size ? DontCare : codes.invert[ins[-size..-1].to_sym] nxt = outs[0...size] == '-' * size ? DontCare : codes.invert[outs[0...size].to_sym] ins = ins[0...-size] outs = outs[size..-1] end inputs << ins.split(//).map(&:to_sym) outputs << outs.split(//).map(&:to_sym) state << (st == '*' ? DontCare : st.to_sym) next_state << (nxt == '*' ? DontCare : nxt.to_sym) end # FIXME: the below hack makes state have all possible values by expanding a don’t-care a bit (if present) (next_state - state - [DontCare]).each do |missing_state| i = state.index DontCare state << missing_state next_state << next_state[i] inputs << inputs[i] outputs << outputs[i] end if state.index DontCare new inputs.transpose, outputs.transpose, state, next_state, codes end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
45 46 47 |
# File 'lib/art-decomp/fsm.rb', line 45 def == other [@inputs, @outputs, @state, @next_state] == [other.inputs, other.outputs, other.state, other.next_state] end |
#beta_f ⇒ Object
49 50 51 |
# File 'lib/art-decomp/fsm.rb', line 49 def beta_f @outputs.map { |o| Blanket.from_array o }.inject(:*) * Blanket.from_array(@next_state) end |
#beta_q ⇒ Object
53 54 55 |
# File 'lib/art-decomp/fsm.rb', line 53 def beta_q Blanket.from_array @state end |
#beta_qp ⇒ Object
57 58 59 |
# File 'lib/art-decomp/fsm.rb', line 57 def beta_qp Blanket.from_array @next_state end |
#beta_x(ins) ⇒ Object
61 62 63 |
# File 'lib/art-decomp/fsm.rb', line 61 def beta_x ins beta @inputs, ins end |
#beta_y(ins) ⇒ Object
65 66 67 |
# File 'lib/art-decomp/fsm.rb', line 65 def beta_y ins beta @outputs, ins end |
#expand_x(ins) ⇒ Object
71 72 73 74 |
# File 'lib/art-decomp/fsm.rb', line 71 def ins return self unless ins.any? { |i| @inputs[i].include? DontCare } FSM.from_kiss to_kiss.lines.map { |line| line.(ins) }.flatten.sort.join end |
#fsm_cells(archs) ⇒ Object
76 77 78 79 |
# File 'lib/art-decomp/fsm.rb', line 76 def fsm_cells archs return 0 if @outputs.map { |output| Blanket.from_array output }.inject(:*).size < 2 Arch[input_count + beta_q.pins, output_count + beta_q.pins].cells archs end |
#general_relevance ⇒ Object
81 82 83 |
# File 'lib/art-decomp/fsm.rb', line 81 def general_relevance relevance false end |
#hash ⇒ Object
85 86 87 |
# File 'lib/art-decomp/fsm.rb', line 85 def hash @inputs.hash ^ @outputs.hash ^ @state.hash ^ @next_state.hash end |
#implementable_in?(archs) ⇒ Boolean
89 90 91 |
# File 'lib/art-decomp/fsm.rb', line 89 def implementable_in? archs not fsm_cells(archs).nil? end |
#input_count ⇒ Object
93 94 95 |
# File 'lib/art-decomp/fsm.rb', line 93 def input_count @inputs.size end |
#output_count ⇒ Object
102 103 104 |
# File 'lib/art-decomp/fsm.rb', line 102 def output_count @outputs.size end |
#q_encoding(rows) ⇒ Object
97 98 99 100 |
# File 'lib/art-decomp/fsm.rb', line 97 def q_encoding rows # FIXME: consider tr DontCare, '*' encoding @state, rows end |
#state_rows_of_next_state_of(rows) ⇒ Object
106 107 108 109 |
# File 'lib/art-decomp/fsm.rb', line 106 def state_rows_of_next_state_of rows state = @next_state[rows.bits.first] B[*(0...@state.size).select { |i| @state[i] == state or @state[i] == DontCare }] end |
#stats ⇒ Object
111 112 113 |
# File 'lib/art-decomp/fsm.rb', line 111 def stats "#{@inputs.size}/#{@outputs.size}+#{(@state.uniq - [DontCare]).size}s" end |
#structure ⇒ Object
115 116 117 118 119 120 121 |
# File 'lib/art-decomp/fsm.rb', line 115 def structure structure = Hash.new { |state, input| state[input] = {} } @state.each_index do |row| structure[@state[row]][@inputs.transpose[row].join] = {:next_state => @next_state[row], :output => @outputs.transpose[row].join} end structure end |
#to_kiss ⇒ Object
123 124 125 126 127 128 129 130 |
# File 'lib/art-decomp/fsm.rb', line 123 def to_kiss st = @state.map { |e| e == DontCare ? '*' : e } nxt = @next_state.map { |e| e == DontCare ? '*' : e } div = Array.new @state.size, ' ' mid = truth_table? ? [div] : [div, st, div, nxt, div] cols = @inputs + mid + @outputs KISS.new(cols.transpose.map(&:join)).formatted end |
#to_vhdl(name) ⇒ Object
132 133 134 |
# File 'lib/art-decomp/fsm.rb', line 132 def to_vhdl name VHDL.new(self).vhdl name end |
#truth_table? ⇒ Boolean
136 137 138 |
# File 'lib/art-decomp/fsm.rb', line 136 def truth_table? @state.all? { |s| s == DontCare } and @next_state.all? { |ns| ns == DontCare } end |
#unique_relevance ⇒ Object
140 141 142 |
# File 'lib/art-decomp/fsm.rb', line 140 def unique_relevance relevance true end |
#x_encoding(ins, rows) ⇒ Object
144 145 146 |
# File 'lib/art-decomp/fsm.rb', line 144 def x_encoding ins, rows ins.map { |i| encoding @inputs[i], rows }.join end |
#y_encoding(rows) ⇒ Object
148 149 150 |
# File 'lib/art-decomp/fsm.rb', line 148 def y_encoding rows @outputs.map { |output| encoding output, rows }.join end |