Class: BlifUtils::Netlist::Model
- Inherits:
-
Object
- Object
- BlifUtils::Netlist::Model
- 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
-
#clocks ⇒ Object
[Net, … ].
-
#components ⇒ Object
[Component, … ].
-
#inputs ⇒ Object
readonly
[IO, … ].
-
#isBlackBox ⇒ Object
readonly
Returns the value of attribute isBlackBox.
-
#name ⇒ Object
readonly
String.
-
#nets ⇒ Object
[Net, … ].
-
#outputs ⇒ Object
readonly
[IO, … ].
Instance Method Summary collapse
- #add_output_buffers ⇒ Object
- #analyze ⇒ Object
- #analyze_to_hash ⇒ Object
- #clone ⇒ Object
- #create_vhdl_file(topLevel = false) ⇒ Object
-
#initialize(name, inputs, outputs, components, nets, clocks, isBlackBox = false) ⇒ Model
constructor
A new instance of Model.
-
#inspect ⇒ Object
To prevent 36548 lines of output ##.
- #is_blackbox? ⇒ Boolean
- #is_self_contained? ⇒ Boolean
-
#level ⇒ Object
Returns the logic level of the circuit, nil if the model includes subcircuits, or false if the model contains combinatorial loops.
- #level_analysis(withOutputGraphviz: false, quiet: false) ⇒ Object
- #remove_buffers ⇒ Object
- #rename_nets ⇒ Object
- #set_undefined_latches_clock(clk) ⇒ Object
- #set_undefined_latches_initial_value(value) ⇒ Object
- #set_undefined_latches_type(type) ⇒ Object
- #simulation_components_to_schedule_stack(withOutputGraphviz: false, quiet: false) ⇒ Object
- #to_blif ⇒ Object
- #to_vhdl(topLevel: false, stream: "") ⇒ Object
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
#clocks ⇒ Object
- Net, …
308 309 310 |
# File 'lib/blifutils/netlist.rb', line 308 def clocks @clocks end |
#components ⇒ Object
- Component, …
306 307 308 |
# File 'lib/blifutils/netlist.rb', line 306 def components @components end |
#inputs ⇒ Object (readonly)
- IO, …
304 305 306 |
# File 'lib/blifutils/netlist.rb', line 304 def inputs @inputs end |
#isBlackBox ⇒ Object (readonly)
Returns the value of attribute isBlackBox.
309 310 311 |
# File 'lib/blifutils/netlist.rb', line 309 def isBlackBox @isBlackBox end |
#name ⇒ Object (readonly)
String
303 304 305 |
# File 'lib/blifutils/netlist.rb', line 303 def name @name end |
#nets ⇒ Object
- Net, …
307 308 309 |
# File 'lib/blifutils/netlist.rb', line 307 def nets @nets end |
#outputs ⇒ Object (readonly)
- IO, …
305 306 307 |
# File 'lib/blifutils/netlist.rb', line 305 def outputs @outputs end |
Instance Method Details
#add_output_buffers ⇒ Object
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 |
#analyze ⇒ Object
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 = " #{@isBlackBox ? 'Black box' : 'Model'} \"#{@name}\" analysis " = [40, .length].max str = '+' + ''.ljust(,'-') + "+\n" str += '|' + .center() + "|\n" str += '+' + ''.ljust(,'-') + "+\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_hash ⇒ Object
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 |
#clone ⇒ Object
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 |
#inspect ⇒ Object
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
329 330 331 |
# File 'lib/blifutils/netlist.rb', line 329 def is_blackbox? return not(not(@isBlackBox)) end |
#is_self_contained? ⇒ 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 |
#level ⇒ Object
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_buffers ⇒ Object
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_nets ⇒ Object
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_blif ⇒ Object
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 |