Class: ArtDecomp::FSM

Inherits:
Object
  • Object
show all
Defined in:
lib/art-decomp/fsm.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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

#codesObject (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_fObject



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_qObject



53
54
55
# File 'lib/art-decomp/fsm.rb', line 53

def beta_q
  Blanket.from_array @state
end

#beta_qpObject



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 expand_x ins
  return self unless ins.any? { |i| @inputs[i].include? DontCare }
  FSM.from_kiss to_kiss.lines.map { |line| line.dc_expand(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_relevanceObject



81
82
83
# File 'lib/art-decomp/fsm.rb', line 81

def general_relevance
  relevance false
end

#hashObject



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

Returns:

  • (Boolean)


89
90
91
# File 'lib/art-decomp/fsm.rb', line 89

def implementable_in? archs
  not fsm_cells(archs).nil?
end

#input_countObject



93
94
95
# File 'lib/art-decomp/fsm.rb', line 93

def input_count
  @inputs.size
end

#output_countObject



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

#statsObject



111
112
113
# File 'lib/art-decomp/fsm.rb', line 111

def stats
  "#{@inputs.size}/#{@outputs.size}+#{(@state.uniq - [DontCare]).size}s"
end

#structureObject



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_kissObject



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

Returns:

  • (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_relevanceObject



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