Class: BlifUtils::Netlist::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/blifutils/netlist.rb,
lib/blifutils/layering.rb,
lib/blifutils/blif_to_vhdl.rb,
lib/blifutils/level_analyzer.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, inputs, outputs, components, nets, clocks, isBlackBox = false) ⇒ Model

Returns a new instance of Model.



311
312
313
314
315
316
317
318
319
# File 'lib/blifutils/netlist.rb', line 311

def initialize (name, inputs, outputs, components, nets, clocks, isBlackBox = false)
	@name = name
	@inputs = inputs
	@outputs = outputs
	@components = components
	@nets = nets
	@isBlackBox = isBlackBox
	@clocks = clocks
end

Instance Attribute Details

#clocksObject

Net, …


308
309
310
# File 'lib/blifutils/netlist.rb', line 308

def clocks
  @clocks
end

#componentsObject

Component, …


306
307
308
# File 'lib/blifutils/netlist.rb', line 306

def components
  @components
end

#inputsObject (readonly)

IO, …


304
305
306
# File 'lib/blifutils/netlist.rb', line 304

def inputs
  @inputs
end

#isBlackBoxObject (readonly)

Returns the value of attribute isBlackBox.



309
310
311
# File 'lib/blifutils/netlist.rb', line 309

def isBlackBox
  @isBlackBox
end

#nameObject (readonly)

String



303
304
305
# File 'lib/blifutils/netlist.rb', line 303

def name
  @name
end

#netsObject

Net, …


307
308
309
# File 'lib/blifutils/netlist.rb', line 307

def nets
  @nets
end

#outputsObject (readonly)

IO, …


305
306
307
# File 'lib/blifutils/netlist.rb', line 305

def outputs
  @outputs
end

Instance Method Details

#add_output_buffersObject



530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
# File 'lib/blifutils/netlist.rb', line 530

def add_output_buffers
	@outputs.each_with_index do |oIO, i|
		newNet = BlifUtils::Netlist::Net.new(oIO.name, nil, [BlifUtils::Netlist::Fanout.new(:output, i)], false, true)
		newBuffer = BlifUtils::Netlist::LogicGate.new([oIO.net], newNet, [[[1], 1]])
		newNet.driver = newBuffer
		fanoutIndexToDelete = oIO.net.fanouts.index{|fanout| fanout.target == :output and fanout.index == i}
		raise "Cannot find actual fanout to delete for output" if fanoutIndexToDelete.nil?
		oIO.net.fanouts[fanoutIndexToDelete].target = newBuffer
		oIO.net.fanouts[fanoutIndexToDelete].index = 0
		oIO.net.isOutput = false
		oIO.net = newNet
		@components << newBuffer
		@nets << newNet
	end
end

#analyzeObject



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/blifutils/netlist.rb', line 358

def analyze
	bannerTitle = " #{@isBlackBox ? 'Black box' : 'Model'} \"#{@name}\" analysis "
	bannerSize = [40, bannerTitle.length].max
	str  = '+' + ''.ljust(bannerSize,'-') + "+\n"
	str += '|' + bannerTitle.center(bannerSize) + "|\n"
	str += '+' + ''.ljust(bannerSize,'-') + "+\n"
	str += "#{@isBlackBox ? 'Black box' : 'Model'} \"#{@name}\"\n"
	str += "  Inputs: #{@inputs.length}\n"
	str += "  Outputs: #{@outputs.length}\n"
	return str if @isBlackBox
	str += "  Nets: #{@nets.length}\n"
	str += "  Edges: #{@nets.collect{|net| net.fanouts.length}.inject(:+)}\n"
	str += "  Nodes: #{@components.length}\n"
	str += "    Latches: #{@components.select{|comp| comp.isLatch?}.length}\n"
	gates = @components.select{|comp| comp.isGate?}
	nbGates = gates.length
	str += "    Logic gates: #{nbGates}\n"
	subcircuits = @components.select{|comp| comp.isSubcircuit?}
	nbSubcircuits = subcircuits.length
	str += "    Sub circuits: #{nbSubcircuits}\n"

	if nbGates > 0 then
		str += "  Gates repartition:\n"
		repartition = Hash.new(0)
		gates.each{|gate| repartition[gate.inputs.length] += 1}
		Hash[repartition.sort].each do |key, val|
			str += "    #{key.to_s.rjust(2)} input#{key > 1 ? 's:' : ': '} #{val.to_s.rjust(4)} #{(val*100/(nbGates.to_f)).round(1).to_s.rjust(5)}%\n"
		end

		nbBuffers = gates.select{|gate| gate.is_buffer?}.length
		nbConstants = gates.select{|gate| gate.is_constant?}.length
		str += "    Buffers:   #{nbBuffers}\n" if nbBuffers > 0
		str += "    Constants: #{nbConstants}\n" if nbConstants > 0
	end

	if nbSubcircuits > 0 then
		str += "  Sub circuits repartition:\n"
		repartition = Hash.new(0)
		subcircuits.each{|subckt| repartition[subckt.modelName] += 1}
		repartition.sort_by{|key, val| val}.each do |key_val|
			str += "    #{key_val[0]}: #{key_val[1]}\n"
		end
	end

	return str
end

#analyze_to_hashObject



406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/blifutils/netlist.rb', line 406

def analyze_to_hash

	res = {}
	res[:name] = String.new(@name)
	res[:nb_inputs]  = @inputs.length
	res[:nb_outputs] = @outputs.length
	res[:is_blackbox] = @isBlackBox
	return res if @isBlackBox
	res[:nb_nets]    = @nets.length
	res[:nb_edges]   = @nets.collect{|net| net.fanouts.length}.inject(:+)
	res[:nb_nodes]   = @components.length
	res[:nb_latches] = @components.count{|comp| comp.isLatch?}
	gates = @components.select{|comp| comp.isGate?}
	res[:nb_gates]    = gates.length
	res[:nb_subckt]  = @components.count{|comp| comp.isSubcircuit?}

	if res[:nb_gates] > 0 then
		repartition = {}
		gates.collect{|g| g.inputs.length}.uniq.sort.each{|n| repartition[n] = 0}
		gates.each{|gate| repartition[gate.inputs.length] += 1}
		gh = {}
		gh[:gates_per_nb_inputs] = repartition
		gh[:nb_buffers] = gates.count{|gate| gate.is_buffer?}
		gh[:nb_constants] = gates.count{|gate| gate.is_constant?}
		res[:gates] = gh
	end

	if res[:nb_subckt] > 0 then
		repartition = Hash.new(0)
		subcircuits.each{|subckt| repartition[subckt.modelName] += 1}
		res[:subckts] = repartition
	end

	return res
end

#cloneObject



513
514
515
516
# File 'lib/blifutils/netlist.rb', line 513

def clone
	## stack level too deep (SystemStackError) if self is too big... =(
	return Marshal.load(Marshal.dump(self))
end

#create_vhdl_file(topLevel = false) ⇒ Object



46
47
48
49
50
51
52
53
54
55
# File 'lib/blifutils/blif_to_vhdl.rb', line 46

def create_vhdl_file (topLevel = false)
	return if @isBlackBox
	fileName = @name + '.vhd'
	file = File.open(fileName, 'w')

	to_vhdl(toplevel: topLevel, stream: file)

	file.close
	STDERR.puts "File \"#{fileName}\" written."
end

#inspectObject

To prevent 36548 lines of output ##



324
325
326
# File 'lib/blifutils/netlist.rb', line 324

def inspect
	return "#<BlifUtils::Netlist::Model:#{object_id} @name=#{@name.inspect}>"
end

#is_blackbox?Boolean

Returns:

  • (Boolean)


329
330
331
# File 'lib/blifutils/netlist.rb', line 329

def is_blackbox?
	return not(not(@isBlackBox))
end

#is_self_contained?Boolean

Returns:

  • (Boolean)


443
444
445
# File 'lib/blifutils/netlist.rb', line 443

def is_self_contained?
	return @components.index{|comp| comp.class == BlifUtils::Netlist::SubCircuit}.nil?
end

#levelObject

Returns the logic level of the circuit, nil if the model includes subcircuits, or false if the model contains combinatorial loops



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/blifutils/level_analyzer.rb', line 32

def level
	return nil unless self.is_self_contained?

	graph = BlifUtils::NetlistGraph::Graph::create_from_model(self)

	start_vertices = graph.vertices.select{|v| v.component.kind_of?(BlifUtils::Netlist::Latch) or v.component.output.isOutput}.uniq

	res = catch(:combinatorial_loop_found) do 
		theMax = 0
		visited_vertices = []
		start_vertices.each do |start|
			follow_combinatorial_path(graph, start, visited_vertices)
			theMax = start.layer if start.layer > theMax
		end
		theMax
	end

	return false unless res
	return res
end

#level_analysis(withOutputGraphviz: false, quiet: false) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/blifutils/level_analyzer.rb', line 83

def level_analysis (withOutputGraphviz: false, quiet: false)
	return unless is_self_contained?

	puts "Generating graph from model components..." unless quiet
	graphFull = BlifUtils::NetlistGraph::Graph.create_from_model(self)
	print "Extracting connected subgraphs... " unless quiet
	graphDAGs = graphFull.get_graph_without_input_output_reg_cst_modinst
	dags = graphDAGs.get_connected_subgraphs
	puts "#{dags.length} subgraph#{dags.length > 1 ? 's' : ''} found"

	print "Checking that there are no cycles in subgraphs...\n" unless quiet
	# Check that all subgraphs are acyclic
	dags.each_with_index do |dag, i|
		unless dag.is_acyclic? then
			str = "\nERROR: There is a combinatorial loop.\n       This subgraph includes components:\n"
			dag.vertices.each do |vertice|
				str += "       Component #{vertice.to_s}\n"
			end
			abort str
		end
	end
	puts "No combinatorial loops found"

	# Do graph layering
	unless quiet then
		print "Layering subgraphs...\n" unless withOutputGraphviz
	end
	maxDagSize = 0
	maxDagLevel = 0
	dags.each_with_index do |dag, i|
		dag.assign_layers_to_vertices
		dagSize = dag.vertices.length
		dagLevel = dag.vertices.collect{|vertice| vertice.layer}.reject{|l| l.nil?}.max
		maxDagSize = dagSize if dagSize != nil and maxDagSize < dagSize
		maxDagLevel = dagLevel if dagLevel != nil and maxDagLevel < dagLevel
		if withOutputGraphviz then
			File.write("#{@name}_graph_DAG_#{i}.gv", dag.to_graphviz)
			puts "Graph #{i.to_s.rjust(2)}: level #{dagLevel.to_s.rjust(2)}, size #{dagSize.to_s.rjust(2)}"
		end

	end

	if withOutputGraphviz then
		File.write("#{@name}_graph_subgraphs.gv", graphDAGs.to_graphviz)
		graphDAGs.vertices.each do |vertice|
			ind = graphFull.vertices.index{|vert| vert.component == vertice.component}
			graphFull.vertices[ind].layer = vertice.layer unless ind.nil?
		end
		File.write("#{@name}_graph_full.gv", graphFull.to_graphviz)
	end

	puts "Maximum number of layers: #{maxDagLevel}"
	puts "Maximum number of gate per subgraph: #{maxDagSize}"
end

#remove_buffersObject



547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# File 'lib/blifutils/netlist.rb', line 547

def remove_buffers
	buffers = @components.select{|comp| comp.isGate?}.select{|gate| gate.is_buffer?}

	buffers.each do |buffer|
		netA = buffer.inputs[0]
		netB = buffer.output

		netAbufferFanoutIndex = netA.fanouts.index{|fanout| fanout.target == buffer and fanout.index == 0}
		if netAbufferFanoutIndex.nil? then
			raise "Cannot find buffer fanout in net"
		end
		netA.fanouts.delete_at(netAbufferFanoutIndex)
		netB.fanouts.each do |fanout|
			if fanout.target.class == BlifUtils::Netlist::LogicGate then
				fanout.target.inputs[fanout.index] = netA
			elsif fanout.target.class == BlifUtils::Netlist::Latch then
				fanout.target.input = netA
			elsif fanout.target.class == BlifUtils::Netlist::SubCircuit then
				fanout.target.inputFormalAcutalList[fanout.index].net = netA
			elsif fanout.target == :output then
				@outputs[fanout.index].net = netA
			else
				raise "WTF?"
			end
			netA.fanouts << fanout
		end
		if netB.isOutput then
			netA.isOutput = true
		end
		@nets.delete(netB)
		@components.delete(buffer)
	end

	buffers = @components.select{|comp| comp.isGate?}.select{|gate| gate.is_buffer?}
end

#rename_netsObject



519
520
521
522
523
524
525
526
527
# File 'lib/blifutils/netlist.rb', line 519

def rename_nets
	i = 0
	@nets.each do |net|
		unless net.isInput then
			net.name = "n#{i.to_s(16).upcase}"
			i += 1
		end
	end
end

#set_undefined_latches_clock(clk) ⇒ Object



342
343
344
345
346
347
# File 'lib/blifutils/netlist.rb', line 342

def set_undefined_latches_clock (clk)
	@components.each do |c|
		next unless c.isLatch? and c.ctrlSig.nil?
		c.set_clock(clk)
	end
end

#set_undefined_latches_initial_value(value) ⇒ Object



350
351
352
353
354
355
# File 'lib/blifutils/netlist.rb', line 350

def set_undefined_latches_initial_value (value)
	@components.each do |c|
		next unless c.isLatch? and c.initValue.nil?
		c.set_initial_value(value)
	end
end

#set_undefined_latches_type(type) ⇒ Object



334
335
336
337
338
339
# File 'lib/blifutils/netlist.rb', line 334

def set_undefined_latches_type (type)
	@components.each do |c|
		next unless c.isLatch? and c.ctrlType.nil?
		c.set_type(type)
	end
end

#simulation_components_to_schedule_stack(withOutputGraphviz: false, quiet: false) ⇒ Object



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/blifutils/layering.rb', line 349

def simulation_components_to_schedule_stack (withOutputGraphviz: false, quiet: false)
	unless is_self_contained? then 
		raise "#{self.class.name}##{__method__.to_s}() requires that the model has no model reference in it. You must flatten the model before."
	end
	puts "Generating graph from model components..." unless quiet
	graphFull = BlifUtils::NetlistGraph::Graph.create_from_model(self)
	print "Extracting connected subgraphs... " unless quiet
	graphDAGs = graphFull.get_graph_without_input_output_reg_cst_modinst
	dags = graphDAGs.get_connected_subgraphs
	puts "#{dags.length} subgraph#{dags.length > 1 ? 's' : ''} found" unless quiet

	print "Checking that there are no cycles in subgraphs... " unless quiet
	# Check that all subgraphs are acyclic
	dags.each_with_index do |dag, i|
		unless dag.is_acyclic? then
			str = "\nERROR: There is a combinatorial loop.\n       (See cycle in file \"#{@name}_graph_DAG_#{i}.gv\")\n       This subgraph includes components:\n"
			dag.vertices.each do |vertice|
				str += "       Component #{vertice.to_s}\n"
			end

			abort str
		end
	end
	puts "Ok" unless quiet

	# Do graph layering
	puts "Layering subgraphs..." unless quiet
	dags.each_with_index do |dag, i|
		dag.assign_layers_to_vertices
		File.write("#{@name}_graph_DAG_#{i}.gv", dag.to_graphviz) if withOutputGraphviz
	end

	File.write("#{@name}_graph_subgraphs.gv", graphDAGs.to_graphviz) if withOutputGraphviz 
	graphDAGs.vertices.each do |vertice|
		ind = graphFull.vertices.index{|vert| vert.component == vertice.component}
		graphFull.vertices[ind].layer = vertice.layer unless ind.nil?
	end
	File.write("#{@name}_graph_full.gv", graphFull.to_graphviz) if withOutputGraphviz 
	puts "Maximum number of layers: #{dags.collect{|dag| dag.vertices.collect{|vertice| vertice.layer}.reject{|l| l.nil?}.max}.reject{|m| m.nil?}.max}" unless quiet

	puts "Writing static schedule for component simulation..." unless quiet
	componentSchedulingStack = []
	dags.each do |dag|
		dag.vertices.sort{|verta, vertb| vertb.layer <=> verta.layer}.each{|vert| componentSchedulingStack << vert.component}
	end
	unless componentSchedulingStack.index{|comp| comp.class != BlifUtils::Netlist::LogicGate}.nil? then
		raise "merde"
	end

	return componentSchedulingStack
end

#to_blifObject



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
# File 'lib/blifutils/netlist.rb', line 448

def to_blif
	str  = ".model #{@name}\n"
	if @isBlackBox then
		tmpstr = ".inputs"
		unless @inputs.empty? then
			@inputs.collect{|io| io.name}.each do |iname|
				if tmpstr.length + iname.length + 3 > 80 then
					tmpstr += " \\\n"
					str += tmpstr
					tmpstr = ''
				end
				tmpstr += ' ' + iname
			end
			str += tmpstr + "\n"
		end
		tmpstr = ".outputs"
		unless @inputs.empty? then
			@outputs.collect{|io| io.name}.each do |iname|
				if tmpstr.length + iname.length + 3 > 80 then
					tmpstr += " \\\n"
					str += tmpstr
					tmpstr = ''
				end
				tmpstr += ' ' + iname
			end
			str += tmpstr + "\n"
		end
		str += ".blackbox\n.end\n"
		return str
	end
	tmpstr = ".inputs"
	unless @inputs.empty? then
		@inputs.collect{|io| io.net.name}.each do |iname|
			if tmpstr.length + iname.length + 3 > 80 then
				tmpstr += " \\\n"
				str += tmpstr
				tmpstr = ''
			end
			tmpstr += ' ' + iname
		end
		str += tmpstr + "\n"
	end
	tmpstr = ".outputs"
	unless @inputs.empty? then
		@outputs.collect{|io| io.net.name}.each do |iname|
			if tmpstr.length + iname.length + 3 > 80 then
				tmpstr += " \\\n"
				str += tmpstr
				tmpstr = ''
			end
			tmpstr += ' ' + iname
		end
		str += tmpstr + "\n"
	end
	#str += "\n"
	@components.select{|comp| comp.isSubcircuit?}.each{|subckt| str += subckt.to_blif}
	#str += "\n"
	@components.select{|comp| comp.isLatch?}.each{|latch| str += latch.to_blif}
	#str += "\n"
	@components.select{|comp| comp.isGate?}.each{|gate| str += gate.to_blif}
	str += ".end\n"
	return str
end

#to_vhdl(topLevel: false, stream: "") ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/blifutils/blif_to_vhdl.rb', line 58

def to_vhdl (topLevel: false, stream: "")
	iNames = @inputs.collect{|io| io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')}
	oNames = @outputs.collect{|io| io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')}
	just = [([0] + iNames.collect{|name| name.length}).max + 3, ([0] + oNames.collect{|name| name.length}).max + 4].max
	entityStr = iNames.collect{|name| "#{(name + '_in').ljust(just)} : in  std_ulogic;"} + 
		oNames.collect{|name| "#{(name + '_out').ljust(just)} : out std_ulogic;"}

	stream << "\nlibrary IEEE;\nuse IEEE.STD_LOGIC_1164.ALL;\n\n\nentity #{@name.upcase} is\n\tport ( "
	stream << entityStr.join("\n\t       ").chop
	stream << ");\nend #{name.upcase};\n\n\n"
	stream << "architecture blif of #{name.upcase} is\n\n"

	just = @nets.collect{|net| net.name.length}.max

	@clocks.reject{|clkname| @nets.collect{|net| net.name}.include?(clkname)}.each do |name|
		stream << "\tsignal #{name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'').ljust(just)} : std_ulogic;\n"
	end
	@nets.each do |net|
		name = net.name
		stream << "\tsignal #{name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'').ljust(just)} : std_ulogic#{if net.driver.kind_of?(BlifUtils::Netlist::Latch) and net.driver.initValue <= 1 then " := '#{net.driver.initValue}'" end};\n"
	end

	stream << "\nbegin\n\n"

	@inputs.each do |io|
		stream << "\t#{io.net.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')} <= #{io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') + '_in'};\n"
	end
	stream <<("\n") unless @inputs.empty?
	@outputs.each do |io|
		stream << "\t#{io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') + '_out'} <= #{io.net.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')};\n"
	end
	stream <<("\n") unless @outputs.empty?

	stream <<("\n")

	latches = @components.select{|comp| comp.kind_of?(BlifUtils::Netlist::Latch)}
	unless latches.empty? then
		clks = latches.collect{|latch| latch.ctrlSig}.reject{|el| el.nil?}.collect{|ctrlsig| if ctrlsig.kind_of?(String) then ctrlsig else ctrlsig.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') end}.uniq

		clks.each do |clkname|
			stream << "\tprocess(#{clkname.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')})\n\tbegin\n\t\tif rising_edge(#{clkname.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')}) then\n"
			latches.select{|latch| latch.ctrlSig != nil and (latch.ctrlSig == clkname or latch.ctrlSig.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') == clkname)}.each do |latch|
				stream << "\t\t\t#{latch.output.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')} <= #{latch.input.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')};\n"
			end
			stream << "\t\tend if;\n\tend process;\n"
		end

		if clks.empty? then
			stream << "\n\tprocess(_clk)\n\tbegin\n\t\tif rising_edge(_clk) then\n"
			latches.select{|latch| latch.ctrlSig.nil?}.each do |latch|
				stream << "\n\t\t\t#{latch.output.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')} <= #{latch.input.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')};\n"
			end
			stream << "\t\tend if;\n\tend process;\n"
		end
		stream <<("\n")
	end

	gates = @components.select{|comp| comp.kind_of?(BlifUtils::Netlist::LogicGate)}
	gates.each do |gate|
		next if gate.is_constant?
		oname = gate.output.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')
		inames = gate.inputs.collect{|net| net.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')}
		stream << "\t#{oname} <= "
		polarity = gate.singleOutputCoverList.collect{|inputs_output| inputs_output[1]}.uniq
		if polarity.length != 1 or (polarity[0] != 0 and polarity[0] != 1) then
			abort "ERROR: Output cover list of gate \"#{oname}\" contains '1' and '0' as output!"
		end
		stream <<("not(") if polarity[0] == 0 
		socvlst = gate.singleOutputCoverList.collect { |cvlst|
			cvlstArr = []
			cvlst[0].each_with_index { |val, i|
				if val == 1 then
					cvlstArr << inames[i]
				elsif val == 0 then
					cvlstArr << "not(#{inames[i]})"
					#else
					#	cvlstArr << "'1'"
				end
			}
			'(' + cvlstArr.join(' and ') + ')'
		}.join(" or\n\t#{' '*oname.length}    ")
		stream << socvlst
		stream <<(")") if polarity[0] == 0 
		stream <<(";\n")
	end
	stream <<("\n") unless gates.empty?

	constants = gates.select{|gate| gate.is_constant?}
	constants.each do |cstGate|
		oname = cstGate.output.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')
		if cstGate.singleOutputCoverList.empty? or cstGate.singleOutputCoverList[0][2] == 0 then
			stream << "\t#{oname} <= '0';\n"
		else
			stream << "\t#{oname} <= '1';\n"
		end
	end
	stream <<("\n") unless constants.empty?

	@components.select{|comp| comp.kind_of?(BlifUtils::Netlist::SubCircuit)}.each_with_index do |subckt, i|
		stream << "\tCMPINST#{i}: entity work.#{subckt.modelName.upcase}\n\tport map ( "

		iNames = subckt.inputFormalAcutalList.collect{|io| io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') + '_in'}
		oNames = subckt.outputFormalAcutalList.collect{|io| io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') + '_out'}
		just = ([0] + iNames.collect{|name| name.length} + oNames.collect{|name| name.length}).max

		portmapStr = subckt.inputFormalAcutalList.collect{|io| "#{(io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') + '_in').ljust(just)} => #{io.net.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')},"} + 
			subckt.outputFormalAcutalList.collect{|io| "#{(io.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'') + '_out').ljust(just)} => #{io.net.name.gsub(/(\[|\])/, '_').gsub(/_$/,'').gsub(/^_/,'')},"}

		stream << portmapStr.join("\n\t           ").chop
		stream << ");\n\n"
	end

	stream << "end blif;\n\n"

	return stream
end