Class: ArtDecomp::FSM

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inputs, outputs, state, next_state) ⇒ FSM

Returns a new instance of FSM.



28
29
30
# File 'lib/art-decomp/fsm.rb', line 28

def initialize inputs, outputs, state, next_state
  @inputs, @outputs, @state, @next_state = inputs.freeze, outputs.freeze, state.freeze, next_state.freeze
end

Class Method Details

.from_kiss(kiss) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/art-decomp/fsm.rb', line 3

def self.from_kiss kiss
  kiss = File.read kiss unless kiss.index "\n"
  inputs, outputs, state, next_state = [], [], [], []
  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
    else next
    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
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



32
33
34
# File 'lib/art-decomp/fsm.rb', line 32

def == other
  [@inputs, @outputs, @state, @next_state] == [other.inputs, other.outputs, other.state, other.next_state]
end

#beta_fObject



36
37
38
# File 'lib/art-decomp/fsm.rb', line 36

def beta_f
  @outputs.map { |o| Blanket.from_array o }.inject(:*) * Blanket.from_array(@next_state)
end

#beta_qObject



40
41
42
# File 'lib/art-decomp/fsm.rb', line 40

def beta_q
  Blanket.from_array @state
end

#beta_qpObject



44
45
46
# File 'lib/art-decomp/fsm.rb', line 44

def beta_qp
  Blanket.from_array @next_state
end

#beta_x(ins) ⇒ Object



48
49
50
# File 'lib/art-decomp/fsm.rb', line 48

def beta_x ins
  beta @inputs, ins
end

#beta_y(ins) ⇒ Object



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

def beta_y ins
  beta @outputs, ins
end

#expand_x(ins) ⇒ Object



58
59
60
61
# File 'lib/art-decomp/fsm.rb', line 58

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



63
64
65
66
# File 'lib/art-decomp/fsm.rb', line 63

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



68
69
70
# File 'lib/art-decomp/fsm.rb', line 68

def general_relevance
  relevance false
end

#hashObject



72
73
74
# File 'lib/art-decomp/fsm.rb', line 72

def hash
  @inputs.hash ^ @outputs.hash ^ @state.hash ^ @next_state.hash
end

#implementable_in?(archs) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/art-decomp/fsm.rb', line 76

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

#input_countObject



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

def input_count
  @inputs.size
end

#output_countObject



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

def output_count
  @outputs.size
end

#q_encoding(rows) ⇒ Object



84
85
86
87
# File 'lib/art-decomp/fsm.rb', line 84

def q_encoding rows
  # FIXME: consider tr DontCare, '*'
  encoding @state, rows
end

#state_rows_of_next_state_of(rows) ⇒ Object



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

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



98
99
100
# File 'lib/art-decomp/fsm.rb', line 98

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

#to_kissObject



102
103
104
105
106
107
108
109
# File 'lib/art-decomp/fsm.rb', line 102

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

#truth_table?Boolean

Returns:

  • (Boolean)


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

def truth_table?
  @state.all? { |s| s == DontCare } and @next_state.all? { |ns| ns == DontCare }
end

#unique_relevanceObject



115
116
117
# File 'lib/art-decomp/fsm.rb', line 115

def unique_relevance
  relevance true
end

#x_encoding(ins, rows) ⇒ Object



119
120
121
# File 'lib/art-decomp/fsm.rb', line 119

def x_encoding ins, rows
  ins.map { |i| encoding @inputs[i], rows }.join
end

#y_encoding(rows) ⇒ Object



123
124
125
# File 'lib/art-decomp/fsm.rb', line 123

def y_encoding rows
  @outputs.map { |output| encoding output, rows }.join
end