blifutils 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|