rtl_circuit 0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/rtl/circuit.rb +136 -0
- data/lib/rtl/code.rb +47 -0
- data/lib/rtl/library.rb +85 -0
- data/lib/rtl/printer.rb +82 -0
- data/lib/rtl.rb +8 -0
- data/tests/json/testing_json.rb +4 -0
- data/tests/pnr/pnr_0.rb +20 -0
- data/tests/pnr/pnr_1.rb +32 -0
- data/tests/pnr/sync_0.rb +18 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ee25e08cf291db2381c60746dd1d654d4931bd0742cdd12f1f85b55b4065f694
|
4
|
+
data.tar.gz: 6a39ac68ccf30ff37ab674dad83ff74686fe81d6e3cf6e1c8b1cca5d0d88c384
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c5af6786663be64b4ff0dff83e240732a48ba17e0980ae7585f7a8d8967f107a81cf106608049829330f6aa094fd777bf9c26543595501ee469b4015ed6eecd2
|
7
|
+
data.tar.gz: 6b633468fc83534bd1164ded8ed001154d378a37c4f37aecde60ec04b14c1ea5cdc762f21565f7291b09dd88eb070a89a7ed811a749a2463c10d905c0a815142
|
data/lib/rtl/circuit.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
module RTL
|
2
|
+
|
3
|
+
class Circuit
|
4
|
+
attr_accessor :name
|
5
|
+
attr_accessor :iname
|
6
|
+
attr_accessor :ports
|
7
|
+
attr_accessor :components
|
8
|
+
attr_accessor :father
|
9
|
+
attr_accessor :signals
|
10
|
+
attr_accessor :properties
|
11
|
+
|
12
|
+
@@id=-1
|
13
|
+
|
14
|
+
def initialize name=nil
|
15
|
+
@name=name
|
16
|
+
@iname="#{name}_#{@@id+=1}"
|
17
|
+
@ports={in:[],out:[]}
|
18
|
+
@signals=[]
|
19
|
+
@components=[]
|
20
|
+
@properties={}
|
21
|
+
@color="cadetblue"
|
22
|
+
end
|
23
|
+
|
24
|
+
def add element
|
25
|
+
port=circuit=sig=element
|
26
|
+
case element
|
27
|
+
when Sig
|
28
|
+
@signals<< sig
|
29
|
+
sig.circuit=self
|
30
|
+
when Port
|
31
|
+
@ports[port.dir] << port
|
32
|
+
port.circuit=self
|
33
|
+
when Circuit
|
34
|
+
@components << circuit
|
35
|
+
circuit.father=self
|
36
|
+
else
|
37
|
+
raise "ERROR : when adding '#{element}'"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def port_named dir,name
|
42
|
+
@ports[dir].find{|p| p.name==name}
|
43
|
+
end
|
44
|
+
|
45
|
+
def port name
|
46
|
+
all=@ports[:in]+@ports[:out]
|
47
|
+
all.flatten.find{|p| p.name==name}
|
48
|
+
end
|
49
|
+
|
50
|
+
def component_named name
|
51
|
+
@components.find{|comp| comp.iname==name}
|
52
|
+
end
|
53
|
+
|
54
|
+
def inputs
|
55
|
+
@ports[:in]
|
56
|
+
end
|
57
|
+
|
58
|
+
def outputs
|
59
|
+
@ports[:out]
|
60
|
+
end
|
61
|
+
|
62
|
+
def wires
|
63
|
+
wires=[]
|
64
|
+
wires << inputs.map{|p| p.fanout}
|
65
|
+
wires << signals.map{|p| p.fanout}
|
66
|
+
wires << components.map{|comp| comp.outputs.map{|o| o.fanout}}
|
67
|
+
wires.flatten
|
68
|
+
end
|
69
|
+
|
70
|
+
def new_instance
|
71
|
+
@@clone_id||={}
|
72
|
+
@@clone_id[name]||=-1
|
73
|
+
@@clone_id[name]+=1
|
74
|
+
clone=Marshal.load(Marshal.dump(self))
|
75
|
+
clone.iname=self.name+"_#{@@clone_id[name]}"
|
76
|
+
clone
|
77
|
+
end
|
78
|
+
|
79
|
+
def make_lib
|
80
|
+
filename="#{name}.lib"
|
81
|
+
File.open(filename,'w') do |f|
|
82
|
+
f.puts Marshal.dump(self)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_dot
|
87
|
+
Printer.new.print self
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Port
|
92
|
+
attr_accessor :dir
|
93
|
+
attr_accessor :name
|
94
|
+
attr_accessor :circuit
|
95
|
+
attr_accessor :fanout
|
96
|
+
attr_accessor :properties
|
97
|
+
def initialize dir,name
|
98
|
+
@dir=dir
|
99
|
+
@name=name
|
100
|
+
@fanout=[]
|
101
|
+
@properties={}
|
102
|
+
end
|
103
|
+
|
104
|
+
def connect port
|
105
|
+
puts "connecting #{self.name}-> #{port.name}" if $verbose
|
106
|
+
@fanout << Wire.new(self,port)
|
107
|
+
end
|
108
|
+
|
109
|
+
def type=(t)
|
110
|
+
@properties[:type]=t
|
111
|
+
end
|
112
|
+
|
113
|
+
def type
|
114
|
+
@properties[:type]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Sig < Port
|
119
|
+
def initialize name
|
120
|
+
super(:out,name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class Wire
|
125
|
+
@@id=-1
|
126
|
+
attr_accessor :name
|
127
|
+
attr_accessor :source,:sink
|
128
|
+
attr_accessor :properties
|
129
|
+
def initialize source,sink
|
130
|
+
@name="w_#{@@id+=1}"
|
131
|
+
@source=source
|
132
|
+
@sink=sink
|
133
|
+
@properties={}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/lib/rtl/code.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
class Code
|
2
|
+
|
3
|
+
attr_accessor :indent,:lines
|
4
|
+
|
5
|
+
def initialize str=nil
|
6
|
+
@lines=[]
|
7
|
+
(@lines << str) if str
|
8
|
+
@indent=0
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(thing)
|
12
|
+
if (code=thing).is_a? Code
|
13
|
+
code.lines.each do |line|
|
14
|
+
@lines << " "*@indent+line.to_s
|
15
|
+
end
|
16
|
+
elsif thing.is_a? Array
|
17
|
+
thing.each do |kode|
|
18
|
+
@lines << kode
|
19
|
+
end
|
20
|
+
elsif thing.nil?
|
21
|
+
else
|
22
|
+
@lines << " "*@indent+thing.to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finalize
|
27
|
+
return @lines.join("\n") if @lines.any?
|
28
|
+
""
|
29
|
+
end
|
30
|
+
|
31
|
+
def newline
|
32
|
+
@lines << " "
|
33
|
+
end
|
34
|
+
|
35
|
+
def save_as filename,verbose=true
|
36
|
+
str=self.finalize
|
37
|
+
File.open(filename,'w'){|f| f.puts(str)}
|
38
|
+
puts "code saved as : #{filename}" if verbose
|
39
|
+
return filename
|
40
|
+
end
|
41
|
+
|
42
|
+
def size
|
43
|
+
@lines.size
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
end
|
data/lib/rtl/library.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative "circuit"
|
2
|
+
|
3
|
+
module RTL
|
4
|
+
|
5
|
+
class UnaryGate < Circuit
|
6
|
+
def initialize
|
7
|
+
name=self.class.to_s.split("::").last
|
8
|
+
super(name)
|
9
|
+
add Port.new(:in,"i")
|
10
|
+
add Port.new(:out,"f")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class BinaryGate < Circuit
|
15
|
+
def initialize
|
16
|
+
name=self.class.to_s.split("::").last
|
17
|
+
super(name)
|
18
|
+
add Port.new(:in,"i1")
|
19
|
+
add Port.new(:in,"i2")
|
20
|
+
add Port.new(:out,"f")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Not < UnaryGate
|
25
|
+
end
|
26
|
+
|
27
|
+
class Or < BinaryGate
|
28
|
+
end
|
29
|
+
|
30
|
+
class And < BinaryGate
|
31
|
+
end
|
32
|
+
|
33
|
+
class Nand < BinaryGate
|
34
|
+
end
|
35
|
+
|
36
|
+
class Nor < BinaryGate
|
37
|
+
end
|
38
|
+
|
39
|
+
class Xor < BinaryGate
|
40
|
+
end
|
41
|
+
|
42
|
+
class Reg < Circuit
|
43
|
+
def initialize
|
44
|
+
name="Reg"
|
45
|
+
super(name)
|
46
|
+
add Port.new(:in ,"d")
|
47
|
+
add Port.new(:out,"q")
|
48
|
+
@color="darkorange"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Mux < Circuit
|
53
|
+
attr_accessor :arity
|
54
|
+
def initialize
|
55
|
+
name="Mux"
|
56
|
+
super(name)
|
57
|
+
@arity=0
|
58
|
+
add Port.new("i0",:in)
|
59
|
+
add Port.new("i1",:in)
|
60
|
+
add Port.new("sel",:in)
|
61
|
+
add Port.new("f",:out)
|
62
|
+
end
|
63
|
+
|
64
|
+
def add port
|
65
|
+
@arity+=1
|
66
|
+
super port
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Add < BinaryGate
|
71
|
+
end
|
72
|
+
|
73
|
+
class Sub < BinaryGate
|
74
|
+
end
|
75
|
+
|
76
|
+
class Mul < BinaryGate
|
77
|
+
end
|
78
|
+
|
79
|
+
class Div < BinaryGate
|
80
|
+
end
|
81
|
+
|
82
|
+
class Rem < BinaryGate
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/lib/rtl/printer.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require_relative 'code'
|
2
|
+
|
3
|
+
module RTL
|
4
|
+
|
5
|
+
class Printer
|
6
|
+
|
7
|
+
def print circuit
|
8
|
+
dot=Code.new
|
9
|
+
dot << "digraph G {"
|
10
|
+
dot.indent=2
|
11
|
+
dot << "graph [rankdir = LR];"
|
12
|
+
circuit.components.each do |comp|
|
13
|
+
inputs_dot ="{"+comp.ports[:in].collect{|e| "<#{e.name}>#{e.name}"}.join("|")+"}"
|
14
|
+
outputs_dot="{"+comp.ports[:out].collect{|e| "<#{e.name}>#{e.name}"}.join("|")+"}"
|
15
|
+
p color=circuit.color
|
16
|
+
dot << "#{comp.iname}[ shape=record; style=filled ; color=#{color} ; label=\"{ #{inputs_dot}| #{comp.name} | #{outputs_dot} }\"];"
|
17
|
+
end
|
18
|
+
circuit.ports[:in].each do |p|
|
19
|
+
dot << "#{p.name}[shape=cds label=\"#{p.name}\"];"
|
20
|
+
end
|
21
|
+
circuit.ports[:out].each do |p|
|
22
|
+
dot << "#{p.name}[shape=cds label=\"#{p.name}\"];"
|
23
|
+
end
|
24
|
+
circuit.signals.each do |sig|
|
25
|
+
dot << "#{sig.name}[shape=point ; xlabel=\"#{sig.name}\"]; /* sig */"
|
26
|
+
end
|
27
|
+
circuit.ports[:in].each do |source|
|
28
|
+
source.fanout.each do |wire|
|
29
|
+
source_name=source.name
|
30
|
+
sink=wire.sink
|
31
|
+
sink_name=sink.name
|
32
|
+
if sink.circuit!=circuit
|
33
|
+
sink_name="#{sink.circuit.iname}:#{sink_name}"
|
34
|
+
end
|
35
|
+
wire_name=wire.name if $verbose
|
36
|
+
dot << "#{source_name} -> #{sink_name} [label=\"#{wire_name}\"]/* pin */"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
circuit.signals.each do |sig|
|
40
|
+
sig.fanout.each do |wire|
|
41
|
+
source_name=sig.name
|
42
|
+
sink =wire.sink
|
43
|
+
sink_name=sink.name
|
44
|
+
if sink.circuit!=circuit
|
45
|
+
sink_name="#{sink.circuit.iname}:#{sink_name}"
|
46
|
+
end
|
47
|
+
wire_name=wire.name if $verbose
|
48
|
+
dot << "#{source_name} -> #{sink_name} [label=\"#{wire_name}\"] /* sig */"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
circuit.components.each do |c|
|
53
|
+
c.ports[:out].each do |p|
|
54
|
+
p.fanout.each do |wire| #pin
|
55
|
+
pout=wire.sink
|
56
|
+
c=pout.circuit==circuit ? "#{pout.name}" : "#{pout.circuit.iname}:#{pout.name}"
|
57
|
+
if c!=p.circuit.iname+":"+p.name
|
58
|
+
wire_name=wire.name if $verbose
|
59
|
+
dot << "#{p.circuit.iname}:#{p.name} -> #{c}[label=\"#{wire_name}\"]; /* tag3 */"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
dot.indent=0
|
65
|
+
dot << "}"
|
66
|
+
dot.save_as "#{circuit.name}.dot",verbose=false
|
67
|
+
end
|
68
|
+
|
69
|
+
def print_svg circuit
|
70
|
+
svg=Code.new
|
71
|
+
svg << "{"
|
72
|
+
svg.indent=2
|
73
|
+
svg << "creator: \"RTL::printer version #{version}\","
|
74
|
+
svg << "modules: "
|
75
|
+
svg.indent=4
|
76
|
+
svg.indent=2
|
77
|
+
svg.indent=0
|
78
|
+
svg << "}"
|
79
|
+
svg
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/rtl.rb
ADDED
data/tests/pnr/pnr_0.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#require "rtl_circuit"
|
2
|
+
require_relative "../../../rtl/lib/rtl.rb"
|
3
|
+
|
4
|
+
include RTL
|
5
|
+
|
6
|
+
top=Circuit.new("top_0")
|
7
|
+
top.add a=Port.new(:in,"a")
|
8
|
+
top.add b=Port.new(:in,"b")
|
9
|
+
top.add f=Port.new(:out,"f")
|
10
|
+
top.add g1=And.new
|
11
|
+
top.add g2=Xor.new
|
12
|
+
|
13
|
+
a.connect g1.port("i1")
|
14
|
+
b.connect g1.port("i2")
|
15
|
+
b.connect g2.port("i2")
|
16
|
+
g1.port("f").connect g2.port("i1")
|
17
|
+
g2.port("f").connect f
|
18
|
+
top.to_dot
|
19
|
+
|
20
|
+
Placer.new.place top
|
data/tests/pnr/pnr_1.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#require "rtl_circuit"
|
2
|
+
require_relative "../../../rtl/lib/rtl.rb"
|
3
|
+
|
4
|
+
include RTL
|
5
|
+
|
6
|
+
top=Circuit.new("top_1")
|
7
|
+
top.add a=Port.new(:in,"a")
|
8
|
+
top.add b=Port.new(:in,"b")
|
9
|
+
top.add c=Port.new(:in,"c")
|
10
|
+
top.add d=Port.new(:in,"d")
|
11
|
+
top.add f=Port.new(:out,"f")
|
12
|
+
|
13
|
+
top.add a1=And.new
|
14
|
+
top.add a2=Or.new
|
15
|
+
top.add a3=Nor.new
|
16
|
+
top.add a4=Nand.new
|
17
|
+
top.add a5=Xor.new
|
18
|
+
|
19
|
+
a.connect a1.port("i1")
|
20
|
+
b.connect a1.port("i2")
|
21
|
+
b.connect a2.port("i1")
|
22
|
+
c.connect a2.port("i2")
|
23
|
+
c.connect a3.port("i1")
|
24
|
+
d.connect a3.port("i2")
|
25
|
+
a2.port("f").connect a4.port("i1")
|
26
|
+
a3.port("f").connect a4.port("i2")
|
27
|
+
a1.port("f").connect a5.port("i1")
|
28
|
+
a4.port("f").connect a5.port("i2")
|
29
|
+
a5.port("f").connect f
|
30
|
+
top.to_dot
|
31
|
+
|
32
|
+
Placer.new.place top
|
data/tests/pnr/sync_0.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "../../../synchrony/lib/synchrony"
|
2
|
+
|
3
|
+
puts "synchrony 1"
|
4
|
+
|
5
|
+
sync= %{
|
6
|
+
circuit sync1
|
7
|
+
input a,b,c,d,e,f,g,h,i,j
|
8
|
+
output o1,o2
|
9
|
+
sig s1
|
10
|
+
s1=(a and !b) or (c and d)
|
11
|
+
o1=((e and f) xor s1) and g
|
12
|
+
o2=(e and f) or (s1 and h) and reg(i or j)
|
13
|
+
end
|
14
|
+
}
|
15
|
+
filename="sync_0.syc"
|
16
|
+
File.open(filename,'w'){|f| f.puts(sync)}
|
17
|
+
|
18
|
+
Synchrony::Compiler.new.compile filename
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rtl_circuit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.7'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jean-Christophe Le Lann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-02-16 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: simple digital circuit modeling, with hierarchy and graphviz output
|
14
|
+
email: jean-christophe.le_lann@ensta-bretagne.fr
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/rtl.rb
|
20
|
+
- lib/rtl/circuit.rb
|
21
|
+
- lib/rtl/code.rb
|
22
|
+
- lib/rtl/library.rb
|
23
|
+
- lib/rtl/printer.rb
|
24
|
+
- tests/json/testing_json.rb
|
25
|
+
- tests/pnr/pnr_0.rb
|
26
|
+
- tests/pnr/pnr_1.rb
|
27
|
+
- tests/pnr/sync_0.rb
|
28
|
+
homepage: http://www.github.com/JC-LL/rtl
|
29
|
+
licenses:
|
30
|
+
- GPL-2.0-only
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubygems_version: 3.0.6
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: simple digital circuit modeling
|
51
|
+
test_files: []
|