VCD writer works
This commit is contained in:
parent
370672e25e
commit
97cf1a74c5
@ -6,3 +6,4 @@ require_relative "rcircuit/and.rb"
|
|||||||
require_relative "rcircuit/or.rb"
|
require_relative "rcircuit/or.rb"
|
||||||
require_relative "rcircuit/xor.rb"
|
require_relative "rcircuit/xor.rb"
|
||||||
require_relative "rcircuit/adder.rb"
|
require_relative "rcircuit/adder.rb"
|
||||||
|
require_relative "rcircuit/vcd.rb"
|
||||||
|
@ -2,91 +2,62 @@
|
|||||||
|
|
||||||
require "set"
|
require "set"
|
||||||
|
|
||||||
def create_vcd_id(index)
|
|
||||||
#VCD uses short id codes for signals.
|
|
||||||
#Generate a unique id given a numeric index, 'a' to 'z'
|
|
||||||
#then 'aa', ab',...
|
|
||||||
new_id = ""
|
|
||||||
loop do
|
|
||||||
new_id = ('a'.ord + index%26).chr + new_id
|
|
||||||
index = (index - index%26)
|
|
||||||
break if index < 1
|
|
||||||
index = index / 26 - 1
|
|
||||||
end
|
|
||||||
return new_id
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_vcd_id
|
|
||||||
[0, 1, 25, 26, 30, 26*26-1, 26*26, 27*26, 27*26+1].each do |i|
|
|
||||||
puts "#{i} -> #{create_vcd_id(i)}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
#test_vcd_id()
|
|
||||||
|
|
||||||
class VCD
|
class VCD
|
||||||
|
|
||||||
def initialize(filename, timescale="1ps")
|
def initialize(filename, timescale="1ps")
|
||||||
@fd = File.open(filename, 'w')
|
@fd = File.open(filename, 'w')
|
||||||
@time=0
|
@time=0
|
||||||
@id_index = 0
|
|
||||||
@changeset = Set.new()
|
|
||||||
@timescale = timescale
|
@timescale = timescale
|
||||||
@portmap = {}
|
@portmap = {}
|
||||||
@idmap = {}
|
@idmap = {}
|
||||||
|
@id = "a"
|
||||||
write_header
|
write_header
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
@portmap.keys.each do |portname|
|
@fd.puts "$scope module TOP $end"
|
||||||
port = @portmap[portname]
|
@portmap.each do |portname,port|
|
||||||
id = @idmap[portname]
|
id = @idmap[portname]
|
||||||
@fd.write("$var wire #{port.width} #{id} #{portname} $end\n")
|
@fd.puts "$var wire #{port.width} #{id} #{portname} $end"
|
||||||
end
|
end
|
||||||
@fd.write("$dumpvars\n")
|
@fd.puts "$upscope $end"
|
||||||
|
@fd.puts "$enddefinitions $end"
|
||||||
|
@fd.puts "$dumpvars"
|
||||||
@portmap.keys.each do |portname|
|
@portmap.keys.each do |portname|
|
||||||
write_port_state(portname)
|
write_port_state(portname)
|
||||||
end
|
end
|
||||||
@fd.write("$end\n")
|
@fd.puts "$end"
|
||||||
@fd.write("\#0\n")
|
@fd.puts "\#0"
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def finish
|
def finish
|
||||||
@fd.close
|
@fd.close
|
||||||
end
|
end
|
||||||
|
|
||||||
def attach(port, portname=nil)
|
def attach(port, portname)
|
||||||
if portname == nil
|
raise ArgumentError.new("Duplicate port name '#{portname}'") if @portmap.has_key?(portname)
|
||||||
portname = port.to_s
|
if port.width > 1
|
||||||
|
portname="#{portname}[0:#{port.width-1}]"
|
||||||
end
|
end
|
||||||
raise RunTimeError.new("Duplicate port name '#{portname}'") if @portmap.has_key?(portname)
|
@idmap[portname] = @id
|
||||||
@idmap[portname] = create_vcd_id(@id_index)
|
@id=@id.next()
|
||||||
@id_index += 1
|
|
||||||
@portmap[portname] = port
|
@portmap[portname] = port
|
||||||
port.add_callback do |value|
|
port.add_callback do |value|
|
||||||
@changeset.add(portname)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
def advance(timesteps)
|
|
||||||
@time += timesteps
|
|
||||||
@fd.write("\##{@time.to_s}\n")
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
def write
|
|
||||||
#write out any changes and clear the changed set
|
|
||||||
@changeset.each do |portname|
|
|
||||||
write_port_state(portname)
|
write_port_state(portname)
|
||||||
end
|
end
|
||||||
@changeset.clear
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def advance(timesteps)
|
||||||
|
@time += timesteps
|
||||||
|
@fd.puts "\##{@time.to_s}"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
def write_header
|
def write_header
|
||||||
@fd.write("$date\n#{Time.now.asctime}\n$end\n")
|
@fd.puts "$version\nRCircuit VCD Generator Version 0.0\n$end"
|
||||||
@fd.write("$version\nRCircuit VCD Generator Version 0.0\n$end\n")
|
@fd.puts "$date\n#{Time.now.asctime}\n$end"
|
||||||
@fd.write("$timescale #{@timescale} $end\n")
|
@fd.puts "$timescale #{@timescale} $end"
|
||||||
end
|
end
|
||||||
|
|
||||||
def write_port_state(portname)
|
def write_port_state(portname)
|
||||||
@ -95,12 +66,9 @@ class VCD
|
|||||||
if port.width == 1
|
if port.width == 1
|
||||||
state = port.val.to_s
|
state = port.val.to_s
|
||||||
else
|
else
|
||||||
state = "b#{port.val.to_s(2)} " #include a space
|
state = "b#{port.val.to_s(2)} "#include a space
|
||||||
end
|
end
|
||||||
@fd.write(state + @idmap[portname] + "\n")
|
@fd.puts state+@idmap[portname]
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
2
todo.txt
Normal file
2
todo.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Must document VCD and Adder
|
||||||
|
Must add tests for VCD and Device
|
26
tst.vcd
Normal file
26
tst.vcd
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
$version
|
||||||
|
RCircuit VCD Generator Version 0.0
|
||||||
|
$end
|
||||||
|
$date
|
||||||
|
Thu Jul 12 07:57:29 2018
|
||||||
|
$end
|
||||||
|
$timescale 1ps $end
|
||||||
|
$scope module TOP $end
|
||||||
|
$var wire 8 a a[0:7] $end
|
||||||
|
$var wire 8 b b[0:7] $end
|
||||||
|
$upscope $end
|
||||||
|
$enddefinitions $end
|
||||||
|
$dumpvars
|
||||||
|
b0 a
|
||||||
|
b0 b
|
||||||
|
$end
|
||||||
|
#0
|
||||||
|
b1000 a
|
||||||
|
b1010 b
|
||||||
|
#1
|
||||||
|
b10000 a
|
||||||
|
b11101 b
|
||||||
|
#2
|
||||||
|
b0 a
|
||||||
|
b0 b
|
||||||
|
#3
|
Loading…
Reference in New Issue
Block a user