blifutils 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/blifutils +53 -18
- data/lib/blifutils.rb +1 -1
- data/lib/blifutils/ast.rb +4 -4
- data/lib/blifutils/elaborator.rb +55 -39
- data/lib/blifutils/netlist.rb +57 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b983d50091d1cdd6613589e30a03c7e660925aea
|
|
4
|
+
data.tar.gz: e919036b709395235ebde09cc7b32eea3f222874
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a4f0b845afaf9c2c9a91c9730b6e027d939e474a31a2f05f749c182cdde1d5d559d9d657c5b68b9072a4d50608273be3a2229c6a7342dcfe024f73ccc71c383
|
|
7
|
+
data.tar.gz: 1ea094b9a22b94e28c78a890836b55f3d21a77f8435ee5a9df321770cf832a807b5ca7b0b0fe152ef29c5361c505880a960b592dd777f4300d362c634c7a814e
|
data/bin/blifutils
CHANGED
|
@@ -29,27 +29,27 @@ inputFiles = []
|
|
|
29
29
|
optparse = OptionParser.new do |opts|
|
|
30
30
|
# Set a banner, displayed at the top
|
|
31
31
|
# of the help screen.
|
|
32
|
-
opts.banner = "Usage: #{$0} [options] -i file1 file2 ..."
|
|
32
|
+
opts.banner = "Usage: #{File.basename($0)} [options] -i file1 file2 ..."
|
|
33
33
|
|
|
34
|
-
opts.on('-i', '--input FILES', 'Input
|
|
34
|
+
opts.on('-i', '--input FILES', 'Input BLIF files') do |file|
|
|
35
35
|
inputFiles << file
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
options[:blif] = false
|
|
39
39
|
options[:outputBlifName] = nil
|
|
40
|
-
opts.on('-o', '--output [FILE]', 'Output
|
|
40
|
+
opts.on('-o', '--output [FILE]', 'Output BLIF FILE') do |file|
|
|
41
41
|
options[:blif] = true
|
|
42
42
|
options[:outputBlifName] = file
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
options[:
|
|
46
|
-
opts.on('-
|
|
47
|
-
options[:
|
|
45
|
+
options[:printModels] = false
|
|
46
|
+
opts.on('-p', '--print-models', 'Print model names') do
|
|
47
|
+
options[:printModels] = true
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
options[:
|
|
51
|
-
opts.on('-
|
|
52
|
-
options[:
|
|
50
|
+
options[:model] = nil
|
|
51
|
+
opts.on('-m', '--model NAME', 'Name of the model to process') do |mod|
|
|
52
|
+
options[:model] = mod
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
options[:flatten] = false
|
|
@@ -57,14 +57,14 @@ optparse = OptionParser.new do |opts|
|
|
|
57
57
|
options[:flatten] = true
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
options[:
|
|
61
|
-
opts.on('-
|
|
62
|
-
options[:
|
|
60
|
+
options[:simulation] = false
|
|
61
|
+
opts.on('-s', '--simulation', "Create C++ simulation files") do
|
|
62
|
+
options[:simulation] = true
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
options[:
|
|
66
|
-
opts.on('-
|
|
67
|
-
options[:
|
|
65
|
+
options[:vhdl] = false
|
|
66
|
+
opts.on('-v', '--vhdl', "Create a vhdl file") do
|
|
67
|
+
options[:vhdl] = true
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
options[:analyze] = false
|
|
@@ -81,6 +81,20 @@ optparse = OptionParser.new do |opts|
|
|
|
81
81
|
options[:analyzeLevelWithGV] = true
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
options[:default_latch_type] = nil
|
|
85
|
+
opts.on('--default-latch-type TYPE', 'Set undefined latch types to TYPE (re: rising edge, fe: falling edge, al: active low, ah: active high, as: asynchronous)') do |type|
|
|
86
|
+
options[:default_latch_type] = type.to_sym
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
options[:default_latch_clock] = nil
|
|
90
|
+
opts.on('--default-latch-clock NAME', 'Set undefined latch contol signals to NAME') do |name|
|
|
91
|
+
options[:default_latch_clock] = name
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
options[:default_latch_initial_value] = nil
|
|
95
|
+
opts.on('--default-latch-initial-value VALUE', "Set undefined latch initial value to VALUE (0, 1, 2: don't care, 3: undefine)") do |val|
|
|
96
|
+
options[:default_latch_initial_value] = val
|
|
97
|
+
end
|
|
84
98
|
|
|
85
99
|
options[:quiet] = false
|
|
86
100
|
opts.on('-q', '--quiet', "Don't print messages") do
|
|
@@ -90,21 +104,42 @@ optparse = OptionParser.new do |opts|
|
|
|
90
104
|
# This displays the help screen, all programs are
|
|
91
105
|
# assumed to have this option.
|
|
92
106
|
opts.on( '-h', '--help', 'Display this help' ) do
|
|
93
|
-
puts opts
|
|
107
|
+
puts opts.to_s
|
|
94
108
|
exit
|
|
95
109
|
end
|
|
96
110
|
end
|
|
97
111
|
|
|
98
|
-
|
|
112
|
+
begin
|
|
113
|
+
optparse.parse!
|
|
114
|
+
rescue OptionParser::MissingArgument => e
|
|
115
|
+
STDERR.puts e.message
|
|
116
|
+
abort optparse.to_s
|
|
117
|
+
end
|
|
99
118
|
|
|
100
119
|
ARGV.each{|f| inputFiles << f}
|
|
101
120
|
|
|
121
|
+
unless [nil, :re, :fe, :al, :ah, :as].include?(options[:default_latch_type])
|
|
122
|
+
STDERR.puts "Default latch type must be either re, fe, al, ah or as."
|
|
123
|
+
abort optparse.to_s
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
unless options[:default_latch_initial_value].nil?
|
|
127
|
+
unless options[:default_latch_initial_value].match(/^[0123]$/) then
|
|
128
|
+
STDERR.puts "Default latch initial value must be either 0, 1, 2 or 3."
|
|
129
|
+
abort optparse.to_s
|
|
130
|
+
end
|
|
131
|
+
options[:default_latch_initial_value] = options[:default_latch_initial_value].to_i
|
|
132
|
+
end
|
|
102
133
|
|
|
103
134
|
|
|
104
135
|
## Read blif inputs and add models to the netlist ##
|
|
105
136
|
netlist = BlifUtils::Netlist.new
|
|
106
137
|
inputFiles.each do |iFile|
|
|
107
|
-
elNetlist = BlifUtils::Elaborator.elaborate_netlist(BlifUtils::Parser.parse(iFile, quiet: options[:quiet]),
|
|
138
|
+
elNetlist = BlifUtils::Elaborator.elaborate_netlist(BlifUtils::Parser.parse(iFile, quiet: options[:quiet]),
|
|
139
|
+
quiet: options[:quiet],
|
|
140
|
+
default_latch_type: options[:default_latch_type],
|
|
141
|
+
default_latch_clock: options[:default_latch_clock],
|
|
142
|
+
default_latch_initial_value: options[:default_latch_initial_value])
|
|
108
143
|
elNetlist.models.each{|model| netlist.add_model(model)}
|
|
109
144
|
end
|
|
110
145
|
|
data/lib/blifutils.rb
CHANGED
data/lib/blifutils/ast.rb
CHANGED
|
@@ -123,7 +123,7 @@ module BlifUtils
|
|
|
123
123
|
class GenericLatch
|
|
124
124
|
attr_reader :input, :output, :initValue, :ctrlType, :ctrlSig
|
|
125
125
|
|
|
126
|
-
def initialize (input, output, initValue:
|
|
126
|
+
def initialize (input, output, initValue: nil, ctrlType: nil, ctrlSig: nil)
|
|
127
127
|
@input = input
|
|
128
128
|
@output = output
|
|
129
129
|
@initValue = initValue
|
|
@@ -135,9 +135,9 @@ module BlifUtils
|
|
|
135
135
|
str = ' '*indent + "Latch:\n"
|
|
136
136
|
str += ' '*(indent+1) + "Input: \"#{@input}\"\n"
|
|
137
137
|
str += ' '*(indent+1) + "Output: \"#{@output}\"\n"
|
|
138
|
-
str += ' '*(indent+1) + "Initial value: \"#{@initValue}\"\n"
|
|
139
|
-
str += ' '*(indent+1) + "Type: \"#{@
|
|
140
|
-
str += ' '*(indent+1) + "Clock signal: #{@ctrlSig.nil? ? "
|
|
138
|
+
str += ' '*(indent+1) + "Initial value: #{@initValue.nil? ? "undefined" : "\"#{@initValue}\""}\n"
|
|
139
|
+
str += ' '*(indent+1) + "Type: #{@ctrlType.nil? ? "undefined" : "\"#{@ctrlSig}\""}\n"
|
|
140
|
+
str += ' '*(indent+1) + "Clock signal: #{@ctrlSig.nil? ? "undefined" : "\"#{@ctrlSig}\""}\n"
|
|
141
141
|
return str
|
|
142
142
|
end
|
|
143
143
|
end # BlifUtils::AST::GenericLatch
|
data/lib/blifutils/elaborator.rb
CHANGED
|
@@ -26,13 +26,13 @@ module BlifUtils
|
|
|
26
26
|
|
|
27
27
|
module Elaborator
|
|
28
28
|
|
|
29
|
-
def self.elaborate_netlist (ast, quiet: false)
|
|
29
|
+
def self.elaborate_netlist (ast, quiet: false, default_latch_type: nil, default_latch_clock: nil, default_latch_initial_value: nil)
|
|
30
30
|
modelDeclarations = gather_model_declarations(ast)
|
|
31
31
|
|
|
32
32
|
netlist = BlifUtils::Netlist.new
|
|
33
33
|
models = ast.modelList.collect do |modelAst|
|
|
34
34
|
puts "Elaborating model \"#{modelAst.name}\"..." unless quiet
|
|
35
|
-
netlist.add_model(elaborate_model(modelAst, modelDeclarations, quiet: quiet))
|
|
35
|
+
netlist.add_model(elaborate_model(modelAst, modelDeclarations, quiet: quiet, default_latch_type: default_latch_type, default_latch_clock: default_latch_clock, default_latch_initial_value: default_latch_initial_value))
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
return netlist
|
|
@@ -94,7 +94,7 @@ module BlifUtils
|
|
|
94
94
|
end # BlifUtils::Elaborator::gather_model_declarations
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
def self.elaborate_model (modelAst, modelDeclarations, quiet: false)
|
|
97
|
+
def self.elaborate_model (modelAst, modelDeclarations, quiet: false, default_latch_type: nil, default_latch_clock: nil, default_latch_initial_value: nil)
|
|
98
98
|
name = modelAst.name
|
|
99
99
|
inputs = []
|
|
100
100
|
outputs = []
|
|
@@ -154,26 +154,48 @@ module BlifUtils
|
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
+
if default_latch_type then
|
|
158
|
+
components.each do |c|
|
|
159
|
+
next unless c.isLatch? and c.ctrlType.nil?
|
|
160
|
+
c.set_type(default_latch_type)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
if default_latch_clock then
|
|
165
|
+
components.each do |c|
|
|
166
|
+
next unless c.isLatch? and c.ctrlSig.nil?
|
|
167
|
+
c.set_clock(default_latch_clock)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
if default_latch_initial_value then
|
|
172
|
+
components.each do |c|
|
|
173
|
+
next unless c.isLatch? and c.initValue.nil?
|
|
174
|
+
c.set_initial_value(default_latch_initial_value)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
|
|
157
179
|
# Create all nets from their drivers #
|
|
180
|
+
netnames = {}
|
|
158
181
|
inputs.each do |iIO|
|
|
159
182
|
newNet = BlifUtils::Netlist::Net.new(iIO.net, :input, [], true, false)
|
|
183
|
+
netnames[newNet.name] = newNet
|
|
160
184
|
nets << newNet
|
|
161
185
|
iIO.net = newNet
|
|
162
186
|
end
|
|
163
187
|
components.reject{|comp| comp.isSubcircuit?}.each do |component|
|
|
164
188
|
newNet = BlifUtils::Netlist::Net.new(component.output, component, [], false, false)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
end
|
|
189
|
+
abort "ERROR: In model \"#{name}\": net \"#{newNet.name}\" has more than one driver" if netnames[newNet.name]
|
|
190
|
+
netnames[newNet.name] = newNet
|
|
168
191
|
nets << newNet
|
|
169
192
|
component.output = newNet
|
|
170
193
|
end
|
|
171
194
|
components.select{|comp| comp.isSubcircuit?}.each do |subcircuit|
|
|
172
195
|
subcircuit.outputFormalAcutalList.each do |outIO|
|
|
173
196
|
newNet = BlifUtils::Netlist::Net.new(outIO.net, subcircuit, [], false, false)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
end
|
|
197
|
+
abort "ERROR: In model \"#{name}\": net \"#{newNet.name}\" has more than one driver" if netnames[newNet.name]
|
|
198
|
+
netnames[newNet.name] = newNet
|
|
177
199
|
nets << newNet
|
|
178
200
|
outIO.net = newNet
|
|
179
201
|
end
|
|
@@ -181,49 +203,43 @@ module BlifUtils
|
|
|
181
203
|
|
|
182
204
|
# Update nets fanouts #
|
|
183
205
|
outputs.each_with_index do |oIO, i|
|
|
184
|
-
|
|
185
|
-
if
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
nets[index].isOutput = true
|
|
190
|
-
oIO.net = nets[index]
|
|
206
|
+
theNet = netnames[oIO.name]
|
|
207
|
+
abort "ERROR: In model \"#{name}\": output \"#{oIO.name}\" has no driver" if theNet.nil?
|
|
208
|
+
theNet.fanouts << BlifUtils::Netlist::Fanout.new(:output, i)
|
|
209
|
+
theNet.isOutput = true
|
|
210
|
+
oIO.net = theNet
|
|
191
211
|
end
|
|
192
212
|
components.select{|comp| comp.isLatch?}.each do |latch|
|
|
193
|
-
|
|
194
|
-
if
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
nets[index].fanouts << BlifUtils::Netlist::Fanout.new(latch, 0)
|
|
198
|
-
latch.input = nets[index]
|
|
213
|
+
theNet = netnames[latch.input]
|
|
214
|
+
abort "ERROR: In model \"#{name}\": input \"#{latch.input}\" from latch \"#{latch.output.name}\" has no driver" if theNet.nil?
|
|
215
|
+
theNet.fanouts << BlifUtils::Netlist::Fanout.new(latch, 0)
|
|
216
|
+
latch.input = theNet
|
|
199
217
|
end
|
|
200
218
|
components.select{|comp| comp.isGate?}.each do |gate|
|
|
201
219
|
gate.inputs.each_with_index do |gin, i|
|
|
202
|
-
|
|
203
|
-
if
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
nets[index].fanouts << BlifUtils::Netlist::Fanout.new(gate, i)
|
|
207
|
-
gate.inputs[i] = nets[index]
|
|
220
|
+
theNet = netnames[gin]
|
|
221
|
+
abort "ERROR: In model \"#{name}\": input \"#{gin}\" from gate \"#{gate.output.name}\" has no driver" if theNet.nil?
|
|
222
|
+
theNet.fanouts << BlifUtils::Netlist::Fanout.new(gate, i)
|
|
223
|
+
gate.inputs[i] = theNet
|
|
208
224
|
end
|
|
209
225
|
end
|
|
210
226
|
components.select{|comp| comp.isSubcircuit?}.each do |subcircuit|
|
|
211
227
|
subcircuit.inputFormalAcutalList.each_with_index do |iIO, i|
|
|
212
|
-
|
|
213
|
-
if
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
nets[index].fanouts << BlifUtils::Netlist::Fanout.new(subcircuit, i)
|
|
217
|
-
iIO.net = nets[index]
|
|
228
|
+
theNet = netnames[iIO.net]
|
|
229
|
+
abort "ERROR: In model \"#{name}\": input \"#{iIO}\" (formal \"#{iIO.name}\" from reference model \"#{subcircuit.modelName}\" has no driver" if theNet.nil?
|
|
230
|
+
theNet.fanouts << BlifUtils::Netlist::Fanout.new(subcircuit, i)
|
|
231
|
+
iIO.net = theNet
|
|
218
232
|
end
|
|
219
233
|
end
|
|
220
234
|
|
|
221
235
|
clocks = components.select{|comp| comp.isLatch?}.collect{|latch| latch.ctrlSig}.reject{|el| el.nil?}.uniq
|
|
222
236
|
|
|
223
237
|
# Check that each net has at least one fanout #
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
238
|
+
unless quiet then
|
|
239
|
+
nets.each do |net|
|
|
240
|
+
if net.fanouts.empty? and not(clocks.include?(net.name)) then
|
|
241
|
+
STDERR.puts "WARNING: In model \"#{name}\": net \"#{net.name}\" has no fanouts"
|
|
242
|
+
end
|
|
227
243
|
end
|
|
228
244
|
end
|
|
229
245
|
|
|
@@ -233,9 +249,9 @@ module BlifUtils
|
|
|
233
249
|
end # BlifUtils::Elaborator
|
|
234
250
|
|
|
235
251
|
|
|
236
|
-
def self.read(fileName, quiet: false)
|
|
252
|
+
def self.read(fileName, quiet: false, default_latch_type: nil, default_latch_clock: nil, default_latch_initial_value: nil)
|
|
237
253
|
ast = BlifUtils::Parser.parse(fileName, quiet: quiet)
|
|
238
|
-
netlist = BlifUtils::Elaborator.elaborate_netlist(ast, quiet: quiet)
|
|
254
|
+
netlist = BlifUtils::Elaborator.elaborate_netlist(ast, quiet: quiet, default_latch_type: nil, default_latch_clock: nil, default_latch_initial_value: nil)
|
|
239
255
|
return netlist
|
|
240
256
|
end # BlifUtils::read
|
|
241
257
|
|
data/lib/blifutils/netlist.rb
CHANGED
|
@@ -160,7 +160,23 @@ module BlifUtils
|
|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
def to_blif
|
|
163
|
-
|
|
163
|
+
res = ".latch #{@input.name} #{@output.name}"
|
|
164
|
+
if @ctrlType
|
|
165
|
+
res += " #{@ctrlType} "
|
|
166
|
+
if @ctrlSig.nil?
|
|
167
|
+
res += "NIL"
|
|
168
|
+
elsif @ctrlSig.kind_of?(BlifUtils::Netlist::Net)
|
|
169
|
+
res += @ctrlSig.name
|
|
170
|
+
else
|
|
171
|
+
res += @ctrlSig
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
if @initValue
|
|
175
|
+
res += " #{@initValue} "
|
|
176
|
+
end
|
|
177
|
+
res += "\n"
|
|
178
|
+
|
|
179
|
+
return res
|
|
164
180
|
end
|
|
165
181
|
|
|
166
182
|
|
|
@@ -178,6 +194,22 @@ module BlifUtils
|
|
|
178
194
|
return "Latch \"#{@output.name}\""
|
|
179
195
|
end
|
|
180
196
|
|
|
197
|
+
|
|
198
|
+
def set_type (type)
|
|
199
|
+
raise "Type must be one of [nil, :fe, :re, :ah, :al, :as]" unless [nil, :fe, :re, :ah, :al, :as].include?(type)
|
|
200
|
+
@ctrlType = type
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def set_clock (net_or_name)
|
|
205
|
+
@ctrlSig = net_or_name
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def set_initial_value (value)
|
|
210
|
+
raise "Initial value must be an integer in the range 0..3" unless (value.kind_of?(Integer) and value >= 0 and value <= 3)
|
|
211
|
+
@initValue = value
|
|
212
|
+
end
|
|
181
213
|
end # BlifUtils::Netlist::Latch
|
|
182
214
|
|
|
183
215
|
|
|
@@ -299,6 +331,30 @@ module BlifUtils
|
|
|
299
331
|
end
|
|
300
332
|
|
|
301
333
|
|
|
334
|
+
def set_undefined_latches_type (type)
|
|
335
|
+
@components.each do |c|
|
|
336
|
+
next unless c.isLatch? and c.ctrlType.nil?
|
|
337
|
+
c.set_type(type)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def set_undefined_latches_clock (clk)
|
|
343
|
+
@components.each do |c|
|
|
344
|
+
next unless c.isLatch? and c.ctrlSig.nil?
|
|
345
|
+
c.set_clock(clk)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def set_undefined_latches_initial_value (value)
|
|
351
|
+
@components.each do |c|
|
|
352
|
+
next unless c.isLatch? and c.initValue.nil?
|
|
353
|
+
c.set_initial_value(value)
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
|
|
302
358
|
def analyze
|
|
303
359
|
bannerTitle = " #{@isBlackBox ? 'Black box' : 'Model'} \"#{@name}\" analysis "
|
|
304
360
|
bannerSize = [40, bannerTitle.length].max
|