#!/usr/bin/ruby -Ku
require 'kconv'
require 'Win32API'
require 'csv'

##
## netlistchecker_main
## akinobu nishi
## ネットリスト比較プログラム
##

class NetCheck
	def ref_name(f_name_ref)
	  @f_name_ref = f_name_ref.chomp
	end
	def com_name(f_name_com)
	  @f_name_com = f_name_com.chomp
	end
	def alias_name(f_name_alias)
	  @f_name_alias = f_name_alias.chomp
	end
	# 20120611 add
	def pm_chk(v_pm_chk)
	  @v_pm_chk = v_pm_chk
	end
	def run
		print(@v_pm_chk)
		
		##########
		# 初期化
		file_diff = File.open("diff1_out.txt","w")
		file_diff.close
		file_diff = File.open("diff2_out.txt","w")
		file_diff.close
		##########

		## 使用したファイル名をdiff1_out.txtに記述
		file_diff = File.open("diff1_out.txt","a")
		file_diff.write("ref = " + @f_name_ref + "\n")
		file_diff.write("com = " + @f_name_com + "\n")
		file_diff.close
		## 使用したファイル名をdiff2_out.txtに記述
		file_diff = File.open("diff2_out.txt","a")
		file_diff.write("ref = " + @f_name_com + "\n")
		file_diff.write("com = " + @f_name_ref + "\n")
		file_diff.close

		sig_flag2 = 0
		file_loop = File.open(@f_name_ref, "r")		
		total_count = 1
		while file_gets = file_loop.gets
			total_count += 1
		end
		file_loop.close
		
		def file_out(name,type,data)
			file_out = File.open(name,type)
			file_out.write(data)
			file_out.close
		end
		def pin_format_check(din)
			data2 = []
			st = 1
			for i in 1..3
				if(i == 1) # ex) C1(1)
					data1 = din.scan(/\w+\(\w+\)/)
				elsif(i == 2) # ex) C1-1
					data1 = din.scan(/\w+\-\w+/)
				else
					data1 = din.scan(/\w+\.\w+/)
				end
				if(data2.length < data1.length)
					data2 = data1
					st = i
				end
			end
			if(st == 1) # ex) C1(1)
				data = din.gsub(/\(/,".").gsub(/\)/,"") # ( -> . , ) -> ""
			elsif(st == 2) # ex) C1-1
				data = din.gsub(/\-/,".") # "-" -> "."
			else # ex) C1.1
				data = din
			end
			return data
		end
		def sig_pin_scan(din)
			data = []
			for i in 1..5
				if(i == 1)
					din_gsub = din.gsub(/;\s*\n/,"\n").gsub(/:/,";").gsub(/\s*,\s*/," ")
					din_scan = din_gsub.scan(/(\S+)\s*;\s*(.+)\n/)
				elsif(i == 2)
					din_gsub = din.gsub(/\s*,\s*\n*/,' ').gsub(/\s*,\s*/," ")
					din_scan = din_gsub.scan(/(\S+)\s*;\s*(.+)\n/)
				elsif(i == 3)
					din_gsub = din.gsub(/\s*,\s*\n*/,' ')
					din_scan = din_gsub.scan(/(\S+)\s*;\s*(.+)\n/)
				elsif(i == 4)
					din_gsub = din.gsub(/\n/,' ').squeeze(' ').gsub(/\s+\*SIG/,"\n*SIG") + "\n" # 20130313 add "\n"
					din_scan = din_gsub.scan(/\*SIG\s+(\S+)\s*(.+)\n/i)
				elsif(i == 5)
					din_gsub = din.gsub(/\n/,' ').gsub(/\s+\*SIGNAL\*/,"\n*SIGNAL*").gsub("*END*","\n") + "\n" # 20130313 add .gsub("*END*","\n") + "\n"
					din_scan = din_gsub.scan(/\*SIGNAL\*\s+(\S+)\s*(.+)\n/i)
				end
				if(data.length < din_scan.length) # どのパターンに一番当てはまるかどうかを確認する。
					data = din_scan
				end
			end
			return data
		end
		def net_signal(din)
			din_scan = sig_pin_scan(din)
			i = 0
			data_sig = []
			din_scan.each{|data|
				data_sig[i] = din_scan[i].shift
				i += 1
			}
			data_pin = din_scan
			return data_sig
		end
		def net_pin(din)
			din_scan = sig_pin_scan(din)
			i = 0
			data_sig = []
			din_scan.each{|data|
				data_sig[i] = din_scan[i].shift
				i += 1
			}
			data_pin = din_scan
			return data_pin
		end
		def pin_split(din)
			i = 0
			data_pin = []
			din.each{|data|
				data_pin[i] = data.join.split(/\s+/).sort # to_s -> join
				i += 1
			}
			return data_pin
		end
		def pin_compare(str1,ary1)
			ary1.each_with_index{|din,i|
				data = din.index(str1)
				if(data != nil)
					return i
				end
			}
			return nil
		end
		def pin_check(ary_ref,ary_com)
			data2 = []
			ary_ref.each_with_index{|din,i|
				data1 = []
				din.each_with_index{|data,k|
					data1[k] = pin_compare(data,ary_com)
				}
				data2[i] = data1
			}
			return data2
		end
		def row_uniq(din)
			data = []
			din.each_with_index{|din1,i|
				data[i] = din1.uniq
			}
			return data
		end
		def nil_check(din)
			data = []
			din.each_with_index{|din1,i|
				data1 = []
				din1.each_with_index{|din2,k|
					if(din2 == nil)
						data1[i] = din1.compact
						if(data1[i] == [])
							data1[i] = "non"
						end
					end
				}
				data[i] = data1.flatten.compact
			}
			data = data.compact
			return data
		end
		def sub_ary(ary1,ary2,num)
			data = []
			ary1.each_with_index{|din,i|
				data[i] = din - ary2[num[i].join.to_i] # to_s -> join
			}
			return data
		end
		def row_uniq2(din)
			data = []
			din.each_with_index{|din1,i|
				data[i] = din1.uniq.compact
			}
			return data
		end
		def diff_output(ref_com_pin,com_ref_pin,ref_sig,ref_pin,com_sig,com_pin,num1,num2,file_name)
			diff_ref_sig = []
			diff_com_sig = []
			data = "--------------------" + "\n\n"
			file_out(file_name,"a",data)
			ref_sig.each_with_index{|ref_sig,i|
				data = ""
				if(num1[i] == [])
					data = ref_sig + "\n" + ref_com_pin[i].join(" ") + "\n" + "signal not found matching" + "\n\n" # to_s -> join
				elsif(ref_com_pin[i] == [] and com_ref_pin[num1[i].join.to_i] = []) # to_s -> join
					data = ref_sig + " == " + com_sig[num1[i].join.to_i] + "\n" + ref_com_pin[i].join(" ") + " <=> " + com_ref_pin[num1[i].join.to_i].join(" ") + "\n\n" # to_s -> join
				elsif(num1[i].length > 1) # 20130312 add
					num1[i].each{|din|
						data_buf = (ref_pin[i] & com_pin[din.to_i])
						data = data + ref_sig + " ???? " + com_sig[din.to_i] + " match pin ====> " + data_buf.join(" ") + " \n" + (ref_pin[i] - com_pin[din.to_i]).join(" ") + " <=> " + (com_pin[din.to_i] - ref_pin[i]).join(" ") + "\n"
					}
				else
					data = ref_sig + " ?? " + com_sig[num1[i].join.to_i] + "\n" + ref_com_pin[i].join(" ") + " <=> " + com_ref_pin[num1[i].join.to_i].join(" ") + "\n\n" # to_s -> join
					diff_ref_sig.push(ref_sig)
					diff_com_sig.push(com_sig[num1[i].join.to_i])
				end
				file_out(file_name,"a",data)
			}
			data = "not match signal" + "\n" + diff_ref_sig.join(" ") + " <==> " + diff_com_sig.join(" ") + "\n\n"
			file_out(file_name,"a",data)
		end
		data_ref = File.open(@f_name_ref, "r") {|f| f.read }.toutf8
		data_com = File.open(@f_name_com, "r") {|f| f.read }.toutf8
		
		data_ref_format_check = pin_format_check(data_ref)
		data_com_format_check = pin_format_check(data_com)

		data_ref_sig = net_signal(data_ref_format_check)
		data_ref_pin = net_pin(data_ref_format_check)
		data_com_sig = net_signal(data_com_format_check)
		data_com_pin = net_pin(data_com_format_check)
		
		data_ref_pin_split = pin_split(data_ref_pin)
		data_com_pin_split = pin_split(data_com_pin)

		index_ref_com = pin_check(data_ref_pin_split,data_com_pin_split)
		index_com_ref = pin_check(data_com_pin_split,data_ref_pin_split)

		index_ref_com_uniq = row_uniq(index_ref_com)
		index_com_ref_uniq = row_uniq(index_com_ref)

		diff_index_ref_com = nil_check(index_ref_com_uniq)
		diff_index_com_ref = nil_check(index_com_ref_uniq)

		index_ref_com_uniq2 = row_uniq2(index_ref_com_uniq)
		index_com_ref_uniq2 = row_uniq2(index_com_ref_uniq)
		
		diff_pin_ref_com = sub_ary(data_ref_pin_split,data_com_pin_split,index_ref_com_uniq2)
		diff_pin_com_ref = sub_ary(data_com_pin_split,data_ref_pin_split,index_com_ref_uniq2)
		$progressBar.variable.value = 50
		
		diff_output(diff_pin_ref_com,diff_pin_com_ref,data_ref_sig,data_ref_pin_split,data_com_sig,data_com_pin_split,index_ref_com_uniq2,index_com_ref_uniq2,"diff1_out.txt")
		diff_output(diff_pin_com_ref,diff_pin_ref_com,data_com_sig,data_com_pin_split,data_ref_sig,data_ref_pin_split,index_com_ref_uniq2,index_ref_com_uniq2,"diff2_out.txt")
		$progressBar.variable.value = 100
	end
end

debug = 0
if(debug == 1)
	print("input netlist ex)test.net\n")
	f_name_ref	= STDIN.gets.chomp
	print("input netlist ex)test.net\n")
	f_name_com	= STDIN.gets.chomp
	NetCheck = NetCheck.new
	NetCheck.ref_name(f_name_ref)
	NetCheck.com_name(f_name_com)
	NetCheck.pm_chk("1")
	NetCheck.run
	print("\n")
	

	print("完了。\n")
	print("終了するには何かキーを押してください。\n")
	kbhit = Win32API.new('msvcrt','_kbhit',[],'l')
	while true
	  if kbhit.call != 0
		 break
	  end
	end
	puts "\nキーが押されました"
end

##########

