Commit 0456d845 authored by Théotime BOLLENGIER's avatar Théotime BOLLENGIER
Browse files

high_level_arch_generator

parent 43b091ac
*.swp
README.html
This diff is collapsed.
This diff is collapsed.
## Parameters:
# width: CLB matrix width
# height: CLB matrix height
# W: Number of unidirectionnal routing track per routing channel (must be multiple of 2)
# N: Nnumber of BLE per CLB
# I: Number of input per CLB
# K: Number of input per LUT
# fcin: Routing track connections per CLB input / W
# fcout: Routing track connections per CLB output / W
# IOfcin: Routing track connections per IO input / W
# IOfcout: Routing track connections per IO input / W
# IOB: Number of IO per IO block
module ArGen
module VPR_arch_writer
def self.write_vpr_architecture (param = {})
param[:width] = 3 unless param[:width]
param[:height] = 3 unless param[:height]
param[:W] = 8 unless param[:W]
param[:N] = 4 unless param[:N]
param[:K] = 4 unless param[:K]
param[:IOB] = 1 unless param[:IOB]
param[:I] = (param[:K]*(param[:N] + 1))/2 unless param[:I] # "The Effect of LUT and Cluster Size on Deep-Submicron FPGA Performance and Density", Elias Ahmed and Jonathan Rose
param[:fcin] = 0.25 unless param[:fcin]
param[:fcout] = 0.5 unless param[:fcout]
param[:IOfcin] = 0.5 unless param[:IOfcin]
param[:IOfcout] = 0.5 unless param[:IOfcout]
param[:useDefaultVprTiming] = true if param[:useDefaultVprTiming].nil?
str = "<!-- Parameters:\n"
if param[:width] > 0 and param[:height] > 0 then
str += " width: #{param[:width].to_s.rjust(4)} CLB matrix width\n"
str += " height: #{param[:height].to_s.rjust(4)} CLB matrix height\n"
else
str += " width: auto CLB matrix width\n"
str += " height: auto CLB matrix height\n"
end
if param[:W] == 0 then
str += " W: auto Number of unidirectionnal routing track per routing channel (must be multiple of 2)\n"
else
str += " W: #{param[:W].to_s.rjust(4)} Number of unidirectionnal routing track per routing channel (must be multiple of 2)\n"
end
str += " N: #{param[:N].to_s.rjust(4)} Nnumber of BLE per CLB\n"
str += " I: #{param[:I].to_s.rjust(4)} Number of input per CLB\n"
str += " K: #{param[:K].to_s.rjust(4)} Number of input per LUT\n"
str += " fcin: #{param[:fcin].to_s.rjust(4)} Routing track connections per CLB input / W\n"
str += " fcout: #{param[:fcout].to_s.rjust(4)} Routing track connections per CLB output / W\n"
str += " IOB: #{param[:IOB].to_s.rjust(4)} Number of IO per IO block\n"
str += " IOfcin: #{param[:IOfcin].to_s.rjust(4)} Routing track connections per IO input / W\n"
str += " IOfcout: #{param[:IOfcout].to_s.rjust(4)} Routing track connections per IO input / W\n"
str += " useDefaultVprTiming: #{param[:useDefaultVprTiming]} Use timing of VPR sample architecture\n"
str += "-->\n\n"
str += "<architecture>\n\n"
str += "\t<models>\n"
str += "\t</models>\n\n"
if param[:width] > 0 and param[:height] > 0 then
str += "\t<!--\n\t<layout auto=\"#{((param[:width]).to_f / (param[:height]).to_f).round(3)}\"/>\n\t-->\n"
str += "\t<layout width=\"#{param[:width]}\" height=\"#{param[:height]}\"/>\n\n"
else
str += "\t<layout auto=\"1.0\"/>\n\n"
end
str += "\t<device>\n"
str += "\t\t<sizing R_minW_nmos=\"8926\" R_minW_pmos=\"16067\" ipin_mux_trans_size=\"1.222260\"/>\n"
str += "\t\t<timing C_ipin_cblock=\"1.47e-15\" T_ipin_cblock=\"7.247000e-11\"/>\n"
str += "\t\t<area grid_logic_tile_area=\"0\"/>\n"
str += "\t\t<switch_block type=\"wilton\" fs=\"3\"/>\n"
str += "\t\t<chan_width_distr>\n"
str += "\t\t\t<io width=\"1.0\"/>\n"
str += "\t\t\t<x distr=\"uniform\" peak=\"1.0\"/>\n"
str += "\t\t\t<y distr=\"uniform\" peak=\"1.0\"/>\n"
str += "\t\t</chan_width_distr>\n"
str += "\t</device>\n\n"
str += "\t<switchlist>\n"
if param[:useDefaultVprTiming] then
str += "\t\t<switch type=\"mux\" name=\"0\" R=\"551\" Cin=\".77e-15\" Cout=\"4e-15\" Tdel=\"58e-12\" mux_trans_size=\"2.630740\" buf_size=\"27.645901\"/>\n"
else
str += "\t\t<switch type=\"mux\" name=\"0\" R=\"551\" Cin=\".77e-15\" Cout=\"4e-15\" Tdel=\"1e-8\" mux_trans_size=\"2.630740\" buf_size=\"27.645901\"/>\n"
end
str += "\t</switchlist>\n\n"
str += "\t<segmentlist>\n"
str += "\t\t<segment length=\"1\" type=\"unidir\" freq=\"1.0\" Rmetal=\"101\" Cmetal=\"22.5e-15\">\n"
str += "\t\t\t<mux name=\"0\"/>\n"
str += "\t\t\t<sb type=\"pattern\">1 1</sb>\n"
str += "\t\t\t<cb type=\"pattern\">1</cb>\n"
str += "\t\t</segment>\n"
str += "\t</segmentlist>\n\n"
str += "\t<complexblocklist>\n\n"
str += "\t\t<!-- Define I/O pads begin -->\n"
str += "\t\t<pb_type name=\"io\" capacity=\"#{param[:IOB]}\" area=\"0\">\n"
str += "\t\t\t<input name=\"outpad\" num_pins=\"1\"/>\n"
str += "\t\t\t<output name=\"inpad\" num_pins=\"1\"/>\n"
str += "\t\t\t<clock name=\"clock\" num_pins=\"1\"/>\n\n"
str += "\t\t\t<pb_type name=\"inpad\" blif_model=\".input\" num_pb=\"1\">\n"
str += "\t\t\t\t<output name=\"inpad\" num_pins=\"1\"/>\n"
str += "\t\t\t</pb_type>\n\n"
str += "\t\t\t<pb_type name=\"outpad\" blif_model=\".output\" num_pb=\"1\">\n"
str += "\t\t\t\t<input name=\"outpad\" num_pins=\"1\"/>\n"
str += "\t\t\t</pb_type>\n\n"
str += "\t\t\t<interconnect>\n"
str += "\t\t\t\t<direct name=\"inpad\" input=\"inpad.inpad\" output=\"io.inpad\">\n"
if param[:useDefaultVprTiming] then
str += "\t\t\t\t\t<delay_constant max=\"4.243e-11\" in_port=\"inpad.inpad\" out_port=\"io.inpad\"/>\n"
else
str += "\t\t\t\t\t<delay_constant max=\"2e-8\" in_port=\"inpad.inpad\" out_port=\"io.inpad\"/>\n"
end
str += "\t\t\t\t</direct>\n"
str += "\t\t\t\t<direct name=\"outpad\" input=\"io.outpad\" output=\"outpad.outpad\">\n"
if param[:useDefaultVprTiming] then
str += "\t\t\t\t\t<delay_constant max=\"1.394e-11\" in_port=\"io.outpad\" out_port=\"outpad.outpad\"/>\n"
else
str += "\t\t\t\t\t<delay_constant max=\"2e-8\" in_port=\"io.outpad\" out_port=\"outpad.outpad\"/>\n"
end
str += "\t\t\t\t</direct>\n"
str += "\t\t\t</interconnect>\n\n"
str += "\t\t\t<fc default_in_type=\"frac\" default_in_val=\"#{param[:IOfcin]}\" default_out_type=\"frac\" default_out_val=\"#{param[:IOfcout]}\"/>\n\n"
str += "\t\t\t<pinlocations pattern=\"custom\">\n"
str += "\t\t\t\t<loc side=\"left\">io.outpad io.inpad io.clock</loc>\n"
str += "\t\t\t\t<loc side=\"top\">io.outpad io.inpad io.clock</loc>\n"
str += "\t\t\t\t<loc side=\"right\">io.outpad io.inpad io.clock</loc>\n"
str += "\t\t\t\t<loc side=\"bottom\">io.outpad io.inpad io.clock</loc>\n"
str += "\t\t\t</pinlocations>\n\n"
str += "\t\t\t<gridlocations>\n"
str += "\t\t\t\t<loc type=\"perimeter\" priority=\"10\"/>\n"
str += "\t\t\t</gridlocations>\n\n"
str += "\t\t\t<power method=\"ignore\"/>\n"
str += "\t\t</pb_type>\n"
str += "\t\t<!-- Define I/O pads ends -->\n"
str += "\n\t\t<!-- Define general purpose logic block CLB begins -->\n"
str += "\t\t<pb_type name=\"clb\" area=\"0\">\n"
str += "\t\t\t<input name=\"I\" num_pins=\"#{param[:I]}\" equivalent=\"true\"/>\n"
str += "\t\t\t<output name=\"O\" num_pins=\"#{param[:N]}\" equivalent=\"true\"/>\n"
str += "\t\t\t<clock name=\"clk\" num_pins=\"1\"/>\n\n"
str += "\t\t\t<!-- #{param[:K]}-LUT BLE definition begins -->\n"
str += "\t\t\t<pb_type name=\"ble#{param[:K]}\" num_pb=\"#{param[:N]}\">\n"
str += "\t\t\t\t<input name=\"in\" num_pins=\"#{param[:K]}\"/>\n"
str += "\t\t\t\t<output name=\"out\" num_pins=\"1\"/>\n"
str += "\t\t\t\t<clock name=\"clk\" num_pins=\"1\"/> \n\n"
str += "\t\t\t\t<!-- Define LUT #{param[:K]} -->\n"
str += "\t\t\t\t<pb_type name=\"lut#{param[:K]}\" blif_model=\".names\" num_pb=\"1\" class=\"lut\">\n"
str += "\t\t\t\t\t<input name=\"in\" num_pins=\"#{param[:K]}\" port_class=\"lut_in\"/>\n"
str += "\t\t\t\t\t<output name=\"out\" num_pins=\"1\" port_class=\"lut_out\"/>\n"
str += "\t\t\t\t\t<delay_matrix type=\"max\" in_port=\"lut#{param[:K]}.in\" out_port=\"lut#{param[:K]}.out\">\n"
if param[:useDefaultVprTiming] then
str += "\t\t\t\t\t\t235e-12\n"*param[:K]
else
str += "\t\t\t\t\t\t0\n"*param[:K]
end
str += "\t\t\t\t\t</delay_matrix>\n"
str += "\t\t\t\t</pb_type>\n\n"
str += "\t\t\t\t<!-- Define flip-flop -->\n"
str += "\t\t\t\t<pb_type name=\"ff\" blif_model=\".latch\" num_pb=\"1\" class=\"flipflop\">\n"
str += "\t\t\t\t\t<input name=\"D\" num_pins=\"1\" port_class=\"D\"/>\n"
str += "\t\t\t\t\t<output name=\"Q\" num_pins=\"1\" port_class=\"Q\"/>\n"
str += "\t\t\t\t\t<clock name=\"clk\" num_pins=\"1\" port_class=\"clock\"/>\n"
if param[:useDefaultVprTiming] then
str += "\t\t\t\t\t<T_setup value=\"66e-12\" port=\"ff.D\" clock=\"clk\"/>\n"
str += "\t\t\t\t\t<T_clock_to_Q max=\"124e-12\" port=\"ff.Q\" clock=\"clk\"/>\n"
else
str += "\t\t\t\t\t<T_setup value=\"1e-8\" port=\"ff.D\" clock=\"clk\"/>\n"
str += "\t\t\t\t\t<T_clock_to_Q max=\"1e-8\" port=\"ff.Q\" clock=\"clk\"/>\n"
end
str += "\t\t\t\t</pb_type>\n\n"
str += "\t\t\t\t<interconnect>\n"
str += "\t\t\t\t\t<direct name=\"direct1\" input=\"ble#{param[:K]}.in\" output=\"lut#{param[:K]}.in\"/>\n"
str += "\t\t\t\t\t<direct name=\"direct2\" input=\"lut#{param[:K]}.out\" output=\"ff.D\">\n"
str += "\t\t\t\t\t\t<!-- Advanced user option that tells CAD tool to find LUT+FF pairs in netlist -->\n"
str += "\t\t\t\t\t\t<pack_pattern name=\"ble#{param[:K]}\" in_port=\"lut#{param[:K]}.out\" out_port=\"ff.D\"/>\n"
str += "\t\t\t\t\t</direct>\n"
str += "\t\t\t\t\t<direct name=\"direct3\" input=\"ble#{param[:K]}.clk\" output=\"ff.clk\"/> \n"
str += "\t\t\t\t\t<mux name=\"mux1\" input=\"ff.Q lut#{param[:K]}.out\" output=\"ble#{param[:K]}.out\">\n"
if param[:useDefaultVprTiming] then
str += "\t\t\t\t\t\t<delay_constant max=\"25e-12\" in_port=\"lut#{param[:K]}.out[0:0]\" out_port=\"ble#{param[:K]}.out[0:0]\" />\n"
str += "\t\t\t\t\t\t<delay_constant max=\"45e-12\" in_port=\"ff[0:0].Q\" out_port=\"ble#{param[:K]}.out[0:0]\" />\n"
else
str += "\t\t\t\t\t\t<delay_constant max=\"0\" in_port=\"lut#{param[:K]}.out[0:0]\" out_port=\"ble#{param[:K]}.out[0:0]\" />\n"
str += "\t\t\t\t\t\t<delay_constant max=\"0\" in_port=\"ff[0:0].Q\" out_port=\"ble#{param[:K]}.out[0:0]\" />\n"
end
str += "\t\t\t\t\t</mux>\n"
str += "\t\t\t\t</interconnect>\n"
str += "\t\t\t</pb_type>\n"
str += "\t\t\t<!-- #{param[:K]}-LUT BLE definition end -->\n\n"
str += "\t\t\t<interconnect>\n"
if param[:useDefaultVprTiming] then
str += "\t\t\t\t<complete name=\"crossbar\" input=\"clb.I ble#{param[:K]}[#{param[:N] - 1}:0].out\" output=\"ble#{param[:K]}[#{param[:N] - 1}:0].in\"/>\n"
else
str += "\t\t\t\t<complete name=\"crossbar\" input=\"clb.I ble#{param[:K]}[#{param[:N] - 1}:0].out\" output=\"ble#{param[:K]}[#{param[:N] - 1}:0].in\">\n"
str += "\t\t\t\t\t<delay_constant max=\"1e-8\" in_port=\"ble#{param[:K]}[#{param[:N] - 1}:0].out\" out_port=\"ble#{param[:K]}[#{param[:N] - 1}:0].in\" />\n"
str += "\t\t\t\t\t<delay_constant max=\"1e-8\" in_port=\"clb.I\" out_port=\"#{param[:K]}[#{param[:N] - 1}:0].in\" />\n"
str += "\t\t\t\t</complete>\n"
end
str += "\t\t\t\t<complete name=\"clks\" input=\"clb.clk\" output=\"ble#{param[:K]}[#{param[:N] - 1}:0].clk\"/>\n"
str += "\t\t\t\t<direct name=\"clbouts\" input=\"ble#{param[:K]}[#{param[:N] - 1}:0].out\" output=\"clb.O\"/>\n"
str += "\t\t\t</interconnect>\n\n"
str += "\t\t\t<fc default_in_type=\"frac\" default_in_val=\"#{param[:fcin]}\" default_out_type=\"frac\" default_out_val=\"#{param[:fcout]}\"/>\n\n"
str += "\t\t\t<pinlocations pattern=\"spread\"/>\n\n"
str += "\t\t\t<!-- Place this general purpose logic block in any unspecified column -->\n"
str += "\t\t\t<gridlocations>\n"
str += "\t\t\t\t<loc type=\"fill\" priority=\"1\"/>\n"
str += "\t\t\t</gridlocations>\n"
str += "\t\t</pb_type>\n"
str += "\t\t<!-- Define general purpose logic block CLB ends -->\n"
str += "\n\t</complexblocklist>\n\n"
str += "</architecture>\n"
return str
end # self.write_vpr_architecture
end # VPR_arch_writer
end
if __FILE__ == $0 then
require 'optparse'
options = {}
# width: CLB matrix width
# height: CLB matrix height
# W: Number of unidirectionnal routing track per routing channel (must be multiple of 2)
# N: Nnumber of BLE per CLB
# I: Number of input per CLB
# K: Number of input per LUT
# fcin: Routing track connections per CLB input / W
# fcout: Routing track connections per CLB output / W
# IOfcin: Routing track connections per IO input / W
# IOfcout: Routing track connections per IO input / W
# IOB: Number of IO per IO block
# useDefaultVprTiming: use timings of VPR sample arch, otherwise try to simulate delays with VTPRs, with clk_VTPR = 100 MHz
optparse = OptionParser.new do |opts|
# Set a banner, displayed at the top
# of the help screen.
opts.banner = "Usage: #{$0} [options]"
options[:width] = nil
opts.on('-w', '--width INTEGER', Integer, 'Width of the CLB matrix') do |i|
options[:width] = i
end
options[:height] = nil
opts.on('-h', '--height INTEGER', Integer, 'Height of the CLB matrix') do |i|
options[:height] = i
end
options[:W] = nil
opts.on('-W', '--wire_cardinality INTEGER', Integer, 'Number of unidirectionnal routing tracks per routing channel (must be multiple of 2)') do |i|
options[:W] = i
end
options[:N] = nil
opts.on('-N', '--cluster_size INTEGER', Integer, 'Number of BLE per CLB') do |i|
options[:N] = i
end
options[:I] = nil
opts.on('-I', '--cluster_inputs INTEGER', Integer, 'Number of input per CLB') do |i|
options[:I] = i
end
options[:K] = nil
opts.on('-K', '--lut_inputs INTEGER', Integer, 'Number of input per LUT') do |i|
options[:K] = i
end
options[:fcin] = nil
opts.on('--fcin FLOAT', Float, 'CLB input connection flexibility') do |f|
options[:fcin] = f.to_f
end
options[:fcout] = nil
opts.on('--fcout FLOAT', Float, 'CLB output connection flexibility') do |f|
options[:fcout] = f.to_f
end
options[:IOB] = nil
opts.on('--IO_per_block INTEGER', Integer, 'Number of IO per IO block') do |i|
options[:IOB] = i
end
options[:IOfcin] = nil
opts.on('--IOfcin FLOAT', Float, 'IO input connection flexibility') do |f|
options[:IOfcin] = f.to_f
end
options[:IOfcout] = nil
opts.on('--IOfcout FLOAT', Float, 'IO output connection flexibility') do |f|
options[:IOfcout] = f.to_f
end
options[:useDefaultVprTiming] = nil
opts.on('-t', '--vtpr_timing', 'Use VTPR timing approximation (experimental)') do |b|
options[:useDefaultVprTiming] = not(b)
end
options[:outFileName] = nil
opts.on('-o', '--output FILE', 'Output file name') do |str|
options[:outFileName] = str
end
# This displays the help screen, all programs are
# assumed to have this option.
opts.on('--help', 'Display this help') do
puts opts
exit
end
end
# Parse the command-line. Remember there are two forms
# of the parse method. The 'parse' method simply parses
# ARGV, while the 'parse!' method parses ARGV and removes
# any options found there, as well as any parameters for
# the options. What's left is the list of files to resize.
optparse.parse!
abort "Width must be > 0" if options[:width] and (options[:width] < 1)
abort "Height must be > 0" if options[:height] and (options[:height] < 1)
abort "Wire cardinality must be a positive power of two" if options[:W] and (options[:W] < 2 or (options[:W] & 1) != 0)
abort "BLE per CLB must be > 0" if options[:N] and (options[:N] < 1)
abort "Input per LUT must be >= 2" if options[:K] and (options[:K] < 2)
abort "Input per CLB must be > 0" if options[:I] and (options[:I] < 1)
abort "IO per IO block must be > 0" if options[:IOB] and (options[:IOB] < 1)
abort "0 < IOfcin <= 1" if options[:fcin] and (options[:fcin] <= 0.0 or options[:fcin] > 1.0)
abort "0 < IOfcout <= 1" if options[:fcout] and (options[:fcout] <= 0.0 or options[:fcout] > 1.0)
abort "0 < IOfcin <= 1" if options[:IOfcin] and (options[:IOfcin] <= 0.0 or options[:IOfcin] > 1.0)
abort "0 < IOfcout <= 1" if options[:IOfcout] and (options[:IOfcout] <= 0.0 or options[:IOfcout] > 1.0)
str = ArGen::VPR_arch_writer::write_vpr_architecture(options)
if options[:outFileName] then
puts "Writing VPR architecture in file \"#{options[:outFileName]}\""
File.write(options[:outFileName], str)
else
puts str
end
end
module ArGen
module Yavag
module Routing
class Route
attr_reader :netNumber
attr_reader :netName
attr_reader :route
def initialize (netNumber, netName, route)
@netNumber = netNumber
@netName = netName
@route = route
end # initialize
def to_s
str = "\nNet #{@netNumber} (#{@netName})\n\n"
str += @route.collect{|n| n.to_s}.join("\n") + "\n\n"
return str
end # to_s
def find_corresponding_architecture_elements arch
@route.each do |node|
node.find_corresponding_architecture_element(arch)
end
end # find_corresponding_architecture_elements
def follow_route
segments = []
currentSegment = []
@route.each do |node|
next if node.kind_of?(ArGen::Yavag::Routing::Source)
if node.kind_of?(ArGen::Yavag::Routing::Sink) and not(currentSegment.empty?) then
segments << currentSegment.reverse
currentSegment = []
next
end
currentSegment << node
end
## Get architecture resources used ##
resourceSegments = segments.collect{|ndSeg| ndSeg.collect{|nd| nd.architectureRoutingElement}}
resourceSegments.each_with_index do |rSegment, segIndex|
fanoutResource = rSegment[0]
rSegment[1..-1].each_with_index do |faninResource, resourceIndex|
## Find the multiplexer input index ##
if faninResource.kind_of?(ArGen::Yavag::Opin) then
mind = fanoutResource.mux.inputs.index(faninResource)
else
mind = fanoutResource.mux.inputs.index(faninResource.mux)
end
if mind.nil? then
abort "ERROR: Architecture mismatch: #{segments[segIndex][resourceIndex+1]} cannot fanout to #{segments[segIndex][resourceIndex]}"
end
fanoutResource.mux.inputIndex = mind
fanoutResource.mux.net = @netName
fanoutResource = faninResource
fanoutResource.net = @netName if fanoutResource.kind_of?(ArGen::Yavag::Opin)
end
end
end # follow_route
end # Route
class Node
attr_reader :x, :y
attr_reader :to_x, :to_y
attr_reader :num
attr_reader :id
attr_reader :architectureRoutingElement
def initialize (id, num, x, y, to_x = nil, to_y = nil)
@id = id
@num = num
@x = x
@y = y
@to_x = to_x
@to_y = to_y
@architectureRoutingElement = nil
end # initialize
def to_s
return "[ #{self.class.name.gsub(/^.*::/,'')}, (#{@x}, #{@y})#{(@to_x and @to_y) ? " to (#{@to_x}, #{@to_y})":''}, num: #{@num} ]"
end # to_s
end # Node
class Source < Node
def initialize (id, num, x, y, to_x = nil, to_y = nil)
super(id, num, x, y, to_x, to_y)
end # initialize
def to_s
return "Node#{@id.to_s.rjust(6)} SOURCE (#{@x},#{@y})#{(@to_x or @to_y) ? " to (#{@to_x},#{@to_y})":''} #{@num}"
end # to_s
def find_corresponding_architecture_element arch
@architectureRoutingElement = arch.sources.find{|e| e.num == @num and e.x == @x and e.y == @y and e.to_x == @to_x and e.to_y == @to_y}
abort "Cannot find #{ArGen::Yavag::Routing::Node.instance_method(:to_s).bind(self).call} in architecture" if @architectureRoutingElement.nil?
end # find_corresponding_architecture_element
end # Source
class Sink < Node
def initialize (id, num, x, y, to_x = nil, to_y = nil)
super(id, num, x, y, to_x, to_y)
end # initialize
def to_s
return "Node#{@id.to_s.rjust(6)} SINK (#{@x},#{@y})#{(@to_x or @to_y) ? " to (#{@to_x},#{@to_y})":''} #{@num}"
end # to_s
def find_corresponding_architecture_element arch
@architectureRoutingElement = arch.sinks.find{|e| e.num == @num and e.x == @x and e.y == @y and e.to_x == @to_x and e.to_y == @to_y}
abort "Cannot find #{self} in architecture" if @architectureRoutingElement.nil?
end # find_corresponding_architecture_element
end # Sink
class Track < Node
attr_reader :orientation
def initialize (id, num, x, y, orientation, to_x = nil, to_y = nil)
super(id, num, x, y, to_x, to_y)
@orientation = orientation
end # initialize
def to_s
return "Node#{@id.to_s.rjust(6)} #{@orientation} (#{@x},#{@y})#{(@to_x or @to_y) ? " to (#{@to_x},#{@to_y})":''} Track: #{@num}"
end # to_s
def find_corresponding_architecture_element arch
@architectureRoutingElement = arch.tracks.find{|e| e.num == @num and e.x == @x and e.y == @y and e.to_x == @to_x and e.to_y == @to_y and e.orientation == @orientation}
abort "Cannot find #{ArGen::Yavag::Routing::Node.instance_method(:to_s).bind(self).call} in architecture" if @architectureRoutingElement.nil?
end # find_corresponding_architecture_element
end # Track
class Pin < Node
attr_reader :type
def initialize (id, num, x, y, type, to_x = nil, to_y = nil)
super(id, num, x, y, to_x, to_y)
@type = type
end # initialize
end # Pin
class Ipin < Pin
def initialize (id, num, x, y, type, to_x = nil, to_y = nil)
super(id, num, x, y, type, to_x, to_y)
end # initialize
def to_s
return "Node#{@id.to_s.rjust(6)} IPIN (#{@x},#{@y})#{(@to_x or @to_y) ? " to (#{@to_x},#{@to_y})":''} #{@type}: #{@num}"
end # to_s
def find_corresponding_architecture_element arch
@architectureRoutingElement = arch.ipins.find{|e| e.num == @num and e.x == @x and e.y == @y and e.to_x == @to_x and e.to_y == @to_y and e.type == @type}
abort "Cannot find #{ArGen::Yavag::Routing::Node.instance_method(:to_s).bind(self).call} in architecture" if @architectureRoutingElement.nil?
end # find_corresponding_architecture_element
end # Ipin
class Opin < Pin