rtl_circuit 0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|