ecic 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -8
- data/config/locales/help.en.yaml +4 -2
- data/ecic.gemspec +1 -1
- data/lib/ecic/cli.rb +20 -31
- data/lib/ecic/design_generator.rb +9 -8
- data/lib/ecic/file_adder.rb +21 -11
- data/lib/ecic/generate.rb +35 -29
- data/lib/ecic/helpers/library_creation_helper.rb +77 -0
- data/lib/ecic/helpers/source_list_updater.rb +21 -0
- data/lib/ecic/library.rb +59 -16
- data/lib/ecic/library_generator.rb +18 -5
- data/lib/ecic/project.rb +34 -13
- data/lib/ecic/source_file.rb +2 -5
- data/lib/ecic/source_file_info.rb +98 -0
- data/lib/ecic/sv_design_generator.rb +4 -4
- data/lib/ecic/version.rb +1 -1
- data/lib/ecic.rb +4 -2
- data/notes.txt +28 -4
- data/templates/project/config/libraries.rb +4 -6
- data/templates/project/src/design/lib/sources.rb.tt +2 -2
- metadata +6 -4
- data/lib/ecic/helpers/source_file_adder.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1529013358fa74fc927995546738340500b80fcc80aaf96155a761a6696dbf4
|
4
|
+
data.tar.gz: 75a1426a8775b5d267ea9df4f3d32af6ab7f7f87dbbc37ae062f47d8a048ef4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9723f99531c5ef0d17d79360f647ca2f8c24329041c44adf7e769f8b0e09f9b3315694421eb736ba9355f7a2af530c9b23f445ce97e9dc9149eef5ab52597e4b
|
7
|
+
data.tar.gz: 5afaeb4239982741957301afcc184386d1db04701c6fce5f026b8389bc332b8b18c12a760c1364811ad9d38d7c88ee7cf8488be389756ecb3e7032186d540749
|
data/README.md
CHANGED
@@ -161,21 +161,32 @@ If the folder contains files that will normally be overwritten by the framework,
|
|
161
161
|
|
162
162
|
### Add existing RTL files
|
163
163
|
|
164
|
-
To add an existing RTL file to the project, go to the project folder and use the `ecic
|
164
|
+
To add an existing RTL file to the project, go to the project folder and use the `ecic addfile` commmand. This will add all the listed files to your project.
|
165
165
|
|
166
|
-
|
166
|
+
You can specify the library name with the `--lib` option or rely on an implicit library name that is extracted from the full paths of the added files. In the latter case the extracted library name will be equal to the name of the directory just under `src/design` or `src/testbench`. In either case, if the library does not already exist, you will be asked to confirm the creation of it.
|
167
167
|
|
168
|
-
|
168
|
+
For example, given that:
|
169
169
|
|
170
|
-
|
170
|
+
* you have a Unix like terminal
|
171
|
+
* you want to eg. add all design files that have a `.vhd` or `.sv` extention
|
172
|
+
* all design files are placed in subfolders under a `./src/design`
|
173
|
+
* all files for a given RTL library are placed under a folder (of the same name) in the `./src/design`
|
171
174
|
|
172
|
-
|
175
|
+
... then you can use the standard Unix `find` command and leave out the `--lib` option:
|
173
176
|
|
174
|
-
$ ecic
|
177
|
+
$ ecic addfile `find ./src/design -name "*.vhd"` `find ./src/design -name "*.sv"`
|
175
178
|
|
176
|
-
|
179
|
+
Although all files that belong to a given library should be placed in the folder for that library, you can specify files that are placed anywhere in your file system, but this requires using the `--lib` option. For example, to add two existing files named `./foo/bar/some_design.sv` and `../../some/path/outside/the/library/folder/kuku.vhd` to a library called `my_lib`, run:
|
177
180
|
|
178
|
-
$ ecic
|
181
|
+
$ ecic addfile --lib=my_lib ./foo/bar/some_design.sv ../../some/path/outside/the/library/folder/kuku.vhd
|
182
|
+
|
183
|
+
If all your VHDL designs assume to be compiled into one library called `work`, you can just set `--lib=work`, eg.:
|
184
|
+
|
185
|
+
$ ecic addfile --lib=work `find . -name "*.vhd"`
|
186
|
+
|
187
|
+
When adding files to the project, the file extension (eg. .vhd) is used to determine the file type. VHDL files are expected to have a .vhd or .vhdl extension and Verilog/SystemVerilog files are expected to have a .sv og .v extension. You can also specify the file type with a `type=vhdl|sv` option, eg.:
|
188
|
+
|
189
|
+
$ ecic addfile --type=vhdl --lib=my_lib `find ./foo -name "*.*"`
|
179
190
|
|
180
191
|
## Compiling and elaborating RTL files
|
181
192
|
|
data/config/locales/help.en.yaml
CHANGED
@@ -55,14 +55,16 @@ help:
|
|
55
55
|
long: |
|
56
56
|
Add one or more existing design files to a given library in the project!
|
57
57
|
|
58
|
-
Example: ecic addfile my_lib ./foo/bar/some_design.sv ../toto/kuku.vhd
|
58
|
+
Example: ecic addfile --lib=my_lib ./foo/bar/some_design.sv ../toto/kuku.vhd
|
59
59
|
|
60
60
|
This adds the ./foo/bar/some_design.sv ../toto/kuku.vhd files to the library
|
61
|
-
called 'my_lib' by adding these to the
|
61
|
+
called 'my_lib' by adding these to the sources.rb file of the libray.
|
62
62
|
|
63
63
|
Although all files that belong to a given library should be placed in the
|
64
64
|
folder for that library, you can specify files that are placed anywhere
|
65
65
|
in your file system.
|
66
|
+
|
67
|
+
If an added file is located outside the project folder, an absolute path will be used by default.
|
66
68
|
|
67
69
|
generate:
|
68
70
|
short: Generate new testbenches, RTL modules, tests etc.!
|
data/ecic.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ["lib"]
|
21
|
-
|
21
|
+
spec.required_ruby_version = '>= 2.4.4'
|
22
22
|
spec.add_dependency "thor", '~> 0.20'
|
23
23
|
spec.add_dependency "colorize", '~> 0.8'
|
24
24
|
spec.add_dependency "rake", '~> 12.3'
|
data/lib/ecic/cli.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Ecic
|
2
2
|
class CLI < Command
|
3
3
|
|
4
|
-
include Ecic::
|
4
|
+
include Ecic::SourceListUpdater
|
5
5
|
|
6
6
|
class << self
|
7
7
|
def help(shell, subcommand = false)
|
@@ -11,10 +11,6 @@ module Ecic
|
|
11
11
|
shell.say "To get more help on a specific command, try 'ecic help [COMMAND]'"
|
12
12
|
end
|
13
13
|
|
14
|
-
#TBA: Make a function that returns the root folder for the project
|
15
|
-
def root
|
16
|
-
File.expand_path("./tfj2")
|
17
|
-
end
|
18
14
|
end
|
19
15
|
|
20
16
|
check_unknown_options!
|
@@ -56,37 +52,32 @@ module Ecic
|
|
56
52
|
#--------------------------------------------------------------------------
|
57
53
|
# design generator:
|
58
54
|
#--------------------------------------------------------------------------
|
59
|
-
desc "addfile
|
55
|
+
desc "addfile FILENAME...", Help.text('addfile')['short']
|
60
56
|
long_desc Help.text('addfile')['long']
|
57
|
+
option :lib, :type => :string, :banner => 'LIBRARY_NAME', :desc => 'Specify the name of the design library'
|
61
58
|
|
62
|
-
def addfile(
|
59
|
+
def addfile(*file_names)
|
63
60
|
begin
|
64
61
|
root_dir = Project::root
|
65
62
|
if root_dir.nil?
|
66
|
-
shell.error "You must be within an ECIC project before calling this command"
|
63
|
+
shell.error set_color("You must be within an ECIC project before calling this command",Thor::Shell::Color::RED)
|
67
64
|
exit(1)
|
68
65
|
end
|
66
|
+
|
67
|
+
opt = {"lib" => nil}.merge(options)
|
68
|
+
|
69
69
|
project = Project.new(root_dir)
|
70
70
|
project.load_libraries
|
71
|
-
|
72
|
-
unless project.has_library?(lib_name)
|
73
|
-
if yes?("Library '#{lib_name}' does not exist. Create it? [y/n]:")
|
74
|
-
generator = LibraryGenerator.new
|
75
|
-
generator.destination_root = root_dir
|
76
|
-
generator.library_name = lib_name
|
77
|
-
generator.invoke_all
|
78
|
-
else
|
79
|
-
shell.error "Operation aborted!"
|
80
|
-
exit(2)
|
81
|
-
end
|
82
|
-
end
|
71
|
+
lib_name = opt['lib']
|
83
72
|
file_adder = FileAdder.new
|
73
|
+
file_adder.destination_root = root_dir
|
84
74
|
file_adder.library_name = lib_name
|
85
|
-
file_adder.
|
75
|
+
file_adder.project = project
|
76
|
+
file_adder.file_names = file_names
|
86
77
|
file_adder.invoke_all
|
87
78
|
|
88
79
|
rescue Exception => exc
|
89
|
-
shell.error exc.message
|
80
|
+
shell.error set_color(exc.message, Thor::Shell::Color::RED)
|
90
81
|
exit(3)
|
91
82
|
end
|
92
83
|
|
@@ -127,7 +118,6 @@ module Ecic
|
|
127
118
|
option :format, :type => :string, :banner => 'text|json', :desc => 'Specify the output format'
|
128
119
|
option :include_source_files, :type => :boolean, :aliases => '-s', :desc => "Include source files for each library"
|
129
120
|
def libraries
|
130
|
-
|
131
121
|
defaults = {
|
132
122
|
"format" => "text",
|
133
123
|
"include_source_files" => false
|
@@ -136,22 +126,21 @@ module Ecic
|
|
136
126
|
|
137
127
|
root_dir = Project::root
|
138
128
|
if root_dir.nil?
|
139
|
-
shell.error "You must be within an ECIC project before calling this command"
|
129
|
+
shell.error set_color("You must be within an ECIC project before calling this command",Thor::Shell::Color::RED)
|
140
130
|
exit(3)
|
141
131
|
end
|
142
132
|
project = Project.new(root_dir)
|
143
133
|
project.load_libraries
|
144
|
-
|
134
|
+
if opt['include_source_files']
|
135
|
+
# puts "reading source files..."
|
136
|
+
project.load_sources
|
137
|
+
end
|
145
138
|
if opt['format'] == 'json'
|
146
139
|
require 'json'
|
147
140
|
say project.libraries.map{ |lib| lib.to_json(:include_source_files => opt['include_source_files']) }.join(",")
|
148
141
|
else
|
149
|
-
say project.libraries.map{ |lib| lib.
|
142
|
+
say project.libraries.map{ |lib| lib.to_s(:include_source_files => opt['include_source_files']) }.join("\n")
|
150
143
|
end
|
151
144
|
end
|
152
145
|
end
|
153
|
-
end
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
146
|
+
end
|
@@ -3,9 +3,9 @@ module Ecic
|
|
3
3
|
class DesignGenerator < Thor::Group
|
4
4
|
# require source_file_adder
|
5
5
|
include Thor::Actions
|
6
|
-
include Ecic::
|
6
|
+
include Ecic::SourceListUpdater
|
7
7
|
|
8
|
-
attr_writer :
|
8
|
+
attr_writer :library, :design_name, :include_types_pkg
|
9
9
|
|
10
10
|
def self.source_root
|
11
11
|
File.dirname(__FILE__) + '/../../templates/project'
|
@@ -21,7 +21,7 @@ module Ecic
|
|
21
21
|
# end
|
22
22
|
|
23
23
|
def copy_rtl_templates
|
24
|
-
base_name = "
|
24
|
+
base_name = "#{@library.path}/#{@design_name}"
|
25
25
|
@include_types_pkg ||= false
|
26
26
|
if @include_types_pkg
|
27
27
|
template("src/design/lib/pkg_types.vhd.tt", "#{base_name}-pkg_types.vhd")
|
@@ -32,15 +32,16 @@ module Ecic
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def update_src_list
|
35
|
-
src_file = "
|
35
|
+
src_file = "#{@library.path}/sources.rb"
|
36
36
|
create_file src_file unless File.exists?(src_file)
|
37
37
|
@include_types_pkg ||= false
|
38
|
+
#TBA: update these cals to 'Pathname'
|
38
39
|
if @include_types_pkg
|
39
|
-
|
40
|
+
append_to_file(src_file, "source_file('#{@design_name}-pkg_types.vhd')\n"
|
40
41
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
append_to_file(src_file, "source_file('#{@design_name}-pkg_comp.vhd')\n"
|
43
|
+
append_to_file(src_file, "source_file('#{@design_name}-ent.vhd')\n"
|
44
|
+
append_to_file(src_file, "source_file('#{@design_name}-arc_rtl.vhd')\n"
|
44
45
|
end
|
45
46
|
|
46
47
|
end
|
data/lib/ecic/file_adder.rb
CHANGED
@@ -1,21 +1,31 @@
|
|
1
1
|
module Ecic
|
2
|
-
|
3
2
|
class FileAdder < Thor::Group
|
4
3
|
include Thor::Actions
|
5
|
-
include Ecic::
|
4
|
+
include Ecic::SourceListUpdater
|
5
|
+
include Ecic::LibraryCreationHelper
|
6
|
+
require 'pathname'
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
# def self.source_root
|
10
|
-
# File.dirname(__FILE__) + '/../../templates/project'
|
11
|
-
# end
|
8
|
+
attr_accessor :library_name, :file_names, :project
|
12
9
|
|
13
10
|
def add_files_to_source_list
|
14
|
-
|
15
|
-
|
11
|
+
#If a library name is given, then the project must already contain a library with that
|
12
|
+
#name. Otherwise an error message must be returned, because we do not know if it is a
|
13
|
+
#design or testbench library.
|
14
|
+
unless library_name.nil?
|
15
|
+
library = project.get_library(library_name)
|
16
|
+
raise "Unknown library called '#{library_name}'. Please create the library before adding files to it. " if library.nil?
|
17
|
+
end
|
18
|
+
destination_path = Pathname.new(destination_root)
|
19
|
+
file_names.each { |file_name|
|
20
|
+
src_file_info = SourceFileInfo.new(project, file_name, library)
|
21
|
+
raise "Library name could not be determined from the path of '#{file_name}'. Make sure the appropriate library has been created and specify it with the --lib option." if src_file_info.library.nil?
|
22
|
+
# puts "lib name=#{src_file_info.library.name}, lib_path = #{src_file_info.library.path}"
|
23
|
+
if create_library_if_missing(src_file_info.library)
|
24
|
+
add_src_file(src_file_info, destination_path)
|
25
|
+
else
|
26
|
+
say set_color("Skipping #{file_name}",Thor::Shell::Color::BLUE)
|
27
|
+
end
|
16
28
|
}
|
17
29
|
end
|
18
|
-
|
19
30
|
end
|
20
|
-
|
21
31
|
end
|
data/lib/ecic/generate.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Ecic
|
2
2
|
class Generate < Command
|
3
|
+
include Ecic::LibraryCreationHelper
|
3
4
|
|
4
5
|
#--------------------------------------------------------------------------
|
5
6
|
# TESTBENCH generator:
|
@@ -21,20 +22,30 @@ module Ecic
|
|
21
22
|
|
22
23
|
option :just_print, :type => :boolean, :aliases => '-n', :desc => "Don't actually run any commands; just print them."
|
23
24
|
def library(*names)
|
24
|
-
|
25
|
-
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
begin
|
26
|
+
project_root_path = Ecic::Project::root
|
27
|
+
#project_root_path = Dir.pwd
|
28
|
+
#if false
|
29
|
+
if project_root_path.nil?
|
30
|
+
shell.error set_color("You must be within an ECIC project before calling this command",Thor::Shell::Color::RED)
|
31
|
+
exit(1)
|
32
|
+
else
|
33
|
+
# shell.say "Generating library in #{project_root_path}"
|
34
|
+
project = Project.new(project_root_path)
|
35
|
+
project.load_libraries
|
36
|
+
names.each { |lib_name|
|
37
|
+
#TBA: Add option to generate a testbench library as well
|
38
|
+
new_lib = project.design_library(lib_name)
|
39
|
+
if new_lib.already_exists?
|
40
|
+
say set_color("Library called '#{lib_name}' already exists",Thor::Shell::Color::GREEN)
|
41
|
+
else
|
42
|
+
shell.error set_color("Library called '#{lib_name}' could not be generated",Thor::Shell::Color::RED) unless generate_library new_lib
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
rescue Exception => exc
|
47
|
+
shell.error set_color(exc.message,Thor::Shell::Color::RED)
|
48
|
+
exit(3)
|
38
49
|
end
|
39
50
|
end
|
40
51
|
|
@@ -51,26 +62,21 @@ module Ecic
|
|
51
62
|
|
52
63
|
def design(*names)
|
53
64
|
begin
|
54
|
-
lib_name = options[:lib]
|
55
65
|
type = options[:type]
|
56
66
|
root_dir = Project::root
|
57
67
|
if root_dir.nil?
|
58
|
-
shell.error "You must be within an ECIC project before calling this command"
|
68
|
+
shell.error set_color("You must be within an ECIC project before calling this command",Thor::Shell::Color::RED)
|
59
69
|
exit(1)
|
60
70
|
end
|
61
71
|
project = Project.new(root_dir)
|
62
72
|
project.load_libraries
|
63
73
|
# p project.libraries
|
64
74
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
generator.invoke_all
|
71
|
-
else
|
72
|
-
shell.error "Operation aborted!"
|
73
|
-
exit(2)
|
75
|
+
lib = project.design_library(options[:lib])
|
76
|
+
unless lib.already_exists?
|
77
|
+
unless ok_to_create_library? lib
|
78
|
+
say "Operation aborted!"
|
79
|
+
raise SystemExit
|
74
80
|
end
|
75
81
|
end
|
76
82
|
|
@@ -81,7 +87,7 @@ module Ecic
|
|
81
87
|
else
|
82
88
|
incl_types_pkg ||= false
|
83
89
|
if incl_types_pkg
|
84
|
-
shell.error "--types_package option does not apply for Verilog/SystemVerilog generation!"
|
90
|
+
shell.error set_color("--types_package option does not apply for Verilog/SystemVerilog generation!",Thor::Shell::Color::RED)
|
85
91
|
exit(3)
|
86
92
|
end
|
87
93
|
end
|
@@ -92,16 +98,16 @@ module Ecic
|
|
92
98
|
elsif type == 'sv'
|
93
99
|
generator = SvDesignGenerator.new
|
94
100
|
else
|
95
|
-
shell.error "--type option must be set to either 'vhdl' or 'sv'"
|
101
|
+
shell.error set_color("--type option must be set to either 'vhdl' or 'sv'",Thor::Shell::Color::RED)
|
96
102
|
exit(3)
|
97
103
|
end
|
98
104
|
generator.destination_root = root_dir
|
99
|
-
generator.
|
105
|
+
generator.library = lib
|
100
106
|
generator.design_name = design_name
|
101
107
|
generator.invoke_all
|
102
108
|
}
|
103
109
|
rescue Exception => exc
|
104
|
-
shell.error exc.message
|
110
|
+
shell.error set_color(exc.message,Thor::Shell::Color::RED)
|
105
111
|
exit(3)
|
106
112
|
end
|
107
113
|
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Ecic::LibraryCreationHelper
|
2
|
+
|
3
|
+
def create_library_if_missing(library)
|
4
|
+
unless library.already_exists?
|
5
|
+
return ok_to_create_library? library
|
6
|
+
end
|
7
|
+
return true
|
8
|
+
end
|
9
|
+
|
10
|
+
def ok_to_create_library?(library)
|
11
|
+
if must_create_new_library? library
|
12
|
+
return generate_library library
|
13
|
+
end
|
14
|
+
# shell.error set_color("Operation aborted!",Thor::Shell::Color::RED)
|
15
|
+
# exit(2)
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate_library(library)
|
20
|
+
if library.is_valid?
|
21
|
+
generator = Ecic::LibraryGenerator.new
|
22
|
+
generator.destination_root = library.project.root
|
23
|
+
generator.library = library
|
24
|
+
generator.invoke_all
|
25
|
+
library.save
|
26
|
+
else
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def must_create_new_library?(library)
|
34
|
+
return true if @always_create_library
|
35
|
+
options = "[Ynaq]"
|
36
|
+
loop do
|
37
|
+
answer = ask(
|
38
|
+
%[#{library.type.to_s.capitalize} library '#{library.name}' does not exist. Create it? (enter "h" for help) #{options}],
|
39
|
+
:add_to_history => false
|
40
|
+
)
|
41
|
+
case answer
|
42
|
+
when nil
|
43
|
+
say ""
|
44
|
+
return true
|
45
|
+
when is?(:yes), is?(:all), ""
|
46
|
+
return true
|
47
|
+
when is?(:no), is?(:skip)
|
48
|
+
return false
|
49
|
+
when is?(:always)
|
50
|
+
return @always_create_library = true
|
51
|
+
when is?(:quit)
|
52
|
+
say "Aborting..."
|
53
|
+
raise SystemExit
|
54
|
+
else
|
55
|
+
say library_creation_help
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def library_creation_help
|
61
|
+
puts "Options:"
|
62
|
+
puts " Yes : Create the library (default)"
|
63
|
+
puts " No : Continue without creating the library"
|
64
|
+
puts " All : Create the library (and any additional libraries)"
|
65
|
+
puts " Quit : Abort operation"
|
66
|
+
end
|
67
|
+
|
68
|
+
def is?(value) #:nodoc:
|
69
|
+
value = value.to_s
|
70
|
+
if value.size == 1
|
71
|
+
/\A#{value}\z/i
|
72
|
+
else
|
73
|
+
/\A(#{value}|#{value[0, 1]})\z/i
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Ecic::SourceListUpdater
|
2
|
+
def add_src_file(src_file_info, dest_root)
|
3
|
+
#TBA: IF THE absolute_file_path IS OUTSIDE THE PROJECT FOLDER, THEN THE ABSOLUTE FILE PATH MUST BE USED INSTEAD OF 'relative_file_path'
|
4
|
+
src_list_filepath = src_file_info.sources_file_path
|
5
|
+
absolute_file_path = src_file_info.absolute_path
|
6
|
+
# puts "src_list_filepath=#{src_list_filepath}"
|
7
|
+
# puts "absolute_file_path=#{absolute_file_path}"
|
8
|
+
# puts "dest_root=#{dest_root}"
|
9
|
+
if src_file_info.is_outside_project?
|
10
|
+
used_file_ref = absolute_file_path.to_s
|
11
|
+
else
|
12
|
+
used_file_ref = absolute_file_path.relative_path_from(dest_root.join(src_list_filepath.dirname)).to_s
|
13
|
+
end
|
14
|
+
# puts "relative_file_path = #{relative_file_path}"
|
15
|
+
# relative_src_list_filepath = src_list_filepath.relative_path_from(dest_root).to_s
|
16
|
+
# puts "relative_src_list_filepath = relative_src_list_filepath"
|
17
|
+
# src_file = "src/design/#{library_name}/sources.rb.tfj"
|
18
|
+
create_file src_list_filepath unless File.exists?(File.join(dest_root,src_list_filepath))
|
19
|
+
append_to_file src_list_filepath, "source_file('#{used_file_ref}')\n"
|
20
|
+
end
|
21
|
+
end
|
data/lib/ecic/library.rb
CHANGED
@@ -2,56 +2,99 @@ module Ecic
|
|
2
2
|
|
3
3
|
class Library
|
4
4
|
|
5
|
-
attr_accessor :name
|
5
|
+
attr_accessor :name, :path, :project
|
6
6
|
attr_accessor :source_files
|
7
|
+
attr_reader :type
|
7
8
|
|
8
|
-
|
9
|
+
|
10
|
+
def initialize(project, name, type, options={})
|
11
|
+
opt = {:path => nil}.merge(options)
|
9
12
|
@project = project
|
13
|
+
@type = type
|
10
14
|
@name = name
|
15
|
+
default_path = {:testbench => "src/testbench/#{@name}",
|
16
|
+
:design => "src/design/#{@name}"}
|
17
|
+
@path = opt[:path] || default_path[@type]
|
11
18
|
@source_files = []
|
12
19
|
end
|
13
|
-
|
14
|
-
def
|
15
|
-
|
20
|
+
|
21
|
+
def is_valid?
|
22
|
+
begin
|
23
|
+
validate_name
|
24
|
+
return false if already_exists?
|
25
|
+
#TBA: validate unique name as well
|
26
|
+
return true
|
27
|
+
#TBA: 'validate_name' should raise a specific naming exception and only this specific exception should be caught.
|
28
|
+
rescue Exception => exc
|
29
|
+
return false
|
30
|
+
end
|
16
31
|
end
|
17
32
|
|
33
|
+
def save
|
34
|
+
validate_name
|
35
|
+
@project.add_library self
|
36
|
+
end
|
37
|
+
|
38
|
+
def already_exists?
|
39
|
+
@project.has_library?(self)
|
40
|
+
end
|
41
|
+
|
18
42
|
def to_str(options={})
|
43
|
+
to_s(options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s(options={})
|
19
47
|
str = name
|
20
48
|
incl_src_files = options[:include_source_files] || false
|
21
49
|
if incl_src_files
|
22
|
-
str += "
|
50
|
+
str += ":"
|
51
|
+
str += "\n " + source_files.join("\n ") unless source_files.length == 0
|
23
52
|
end
|
24
53
|
str
|
25
54
|
end
|
26
55
|
|
27
56
|
def to_json(options = {})
|
28
57
|
incl_src_files = options[:include_source_files] || false
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
str = {:name => name}.to_json
|
33
|
-
end
|
58
|
+
hash = {:name => name, :path => path}
|
59
|
+
hash[:source_files] = source_files if incl_src_files
|
60
|
+
hash.to_json
|
34
61
|
end
|
35
62
|
|
36
63
|
def load_sources
|
37
|
-
src_file = File.join(@project.root,
|
64
|
+
src_file = File.join(@project.root, @path, 'sources.rb')
|
38
65
|
if File.exists?(src_file)
|
39
66
|
begin
|
67
|
+
puts "reading #{src_file} ..."
|
40
68
|
eval File.read(src_file)
|
41
69
|
rescue Exception => exc
|
42
70
|
raise "Syntax error occurred while reading #{src_file}: #{exc.message}"
|
43
71
|
end
|
44
72
|
else
|
45
|
-
|
73
|
+
# p @path
|
74
|
+
# p @type
|
75
|
+
raise "Could not read sources for #{name} library. #{src_file} file does not exist"
|
46
76
|
end
|
47
77
|
end
|
48
78
|
|
49
|
-
|
50
|
-
|
51
|
-
|
79
|
+
def is_a_testbench?
|
80
|
+
@type == :testbench
|
81
|
+
end
|
82
|
+
|
83
|
+
#Function used in sources.rb file of each library
|
84
|
+
def source_file(path)
|
85
|
+
# puts "Creating new source file"
|
86
|
+
new_src = SourceFile.new(self, path)
|
52
87
|
source_files << new_src
|
53
88
|
new_src
|
54
89
|
end
|
55
90
|
|
91
|
+
###########################################################################
|
92
|
+
protected
|
93
|
+
###########################################################################
|
94
|
+
|
95
|
+
def validate_name
|
96
|
+
raise "#{@name} is not a valid library name. Library names must start with a letter, followed by one or more numbers, letters or underscores" unless /\A[a-zA-Z]\w*\Z/.match(@name)
|
97
|
+
end
|
98
|
+
|
56
99
|
end
|
57
100
|
end
|
@@ -4,21 +4,34 @@ module Ecic
|
|
4
4
|
include Thor::Actions
|
5
5
|
desc 'Generate a new RTL library'
|
6
6
|
|
7
|
-
attr_writer :
|
7
|
+
attr_writer :library
|
8
8
|
|
9
9
|
def self.source_root
|
10
10
|
File.dirname(__FILE__) + '/../../templates/project'
|
11
11
|
end
|
12
12
|
|
13
13
|
def create_library_directory
|
14
|
-
|
14
|
+
src_list_file = File.expand_path("#{destination_root}/#{@library.path}/sources.rb")
|
15
|
+
template("src/design/lib/sources.rb.tt", src_list_file) unless File.exist?(src_list_file)
|
15
16
|
end
|
16
17
|
|
17
18
|
def update_library_list
|
18
19
|
libraries_file = File.expand_path("#{destination_root}/src/config/libraries.rb")
|
19
|
-
empty_directory 'src/config' unless File.exist?(File.dirname(libraries_file))
|
20
|
-
create_file libraries_file unless File.exist?(libraries_file)
|
21
|
-
|
20
|
+
empty_directory 'src/config' unless File.exist?(File.dirname(libraries_file))
|
21
|
+
create_file libraries_file unless File.exist?(libraries_file)
|
22
|
+
case @library.path.to_s
|
23
|
+
when "src/design/#{@library.name}"
|
24
|
+
cmd = "design_library('#{@library.name}')"
|
25
|
+
when "src/testbench/#{@library.name}"
|
26
|
+
cmd = "testbench_library('#{@library.name}')"
|
27
|
+
else
|
28
|
+
if @library.is_a_testbench?
|
29
|
+
cmd = "testbench_library('#{@library.name}', :path => '#{@library.path}')"
|
30
|
+
else
|
31
|
+
cmd = "design_library('#{@library.name}', :path => '#{@library.path}')"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
append_to_file 'src/config/libraries.rb', "#{cmd}\n"
|
22
35
|
end
|
23
36
|
|
24
37
|
end
|
data/lib/ecic/project.rb
CHANGED
@@ -20,13 +20,13 @@ module Ecic
|
|
20
20
|
#from within an ECIC project folder
|
21
21
|
def self.root(path = Pathname.new(Dir.pwd))
|
22
22
|
if File.exists?(File.join(path, SCRIPT_ECIC))
|
23
|
-
return path
|
23
|
+
return File.expand_path(path)
|
24
24
|
elsif path.root?
|
25
25
|
return nil
|
26
26
|
end
|
27
27
|
return root(path.parent)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def load_libraries
|
31
31
|
lib_file = File.join(@root, LIBRARIES_CFG_SCRIPT)
|
32
32
|
if File.exists?(lib_file)
|
@@ -34,26 +34,47 @@ module Ecic
|
|
34
34
|
eval File.read(lib_file)
|
35
35
|
rescue Exception => exc
|
36
36
|
raise "Syntax error occurred while reading #{lib_file}: #{exc.message}"
|
37
|
-
end
|
37
|
+
end
|
38
38
|
# else
|
39
39
|
# raise "Could not read library definitions from #{lib_file}"
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
def has_library?(library)
|
44
|
+
libraries.any? {|l| l.name.eql? library.name}
|
45
|
+
end
|
43
46
|
|
44
|
-
def
|
45
|
-
libraries.
|
47
|
+
def library_mapped_to(path)
|
48
|
+
matching_libraries = libraries.select {|l| l.path.eql? path }
|
49
|
+
raise "Found multiple libraries mapped to '#{path}'" if matching_libraries.length > 1
|
50
|
+
matching_libraries.first
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_library(lib_name)
|
54
|
+
matching_libraries = libraries.select {|l| l.name.eql? lib_name }
|
55
|
+
raise "Found multiple libraries called '#{lib_name}'" if matching_libraries.length > 1
|
56
|
+
matching_libraries.first
|
46
57
|
end
|
47
58
|
|
48
|
-
|
49
|
-
|
50
|
-
#
|
59
|
+
def add_library(lib)
|
60
|
+
raise "A library called '#{lib.name}' already exists" if has_library?(lib)
|
61
|
+
raise "A library is already mapped to '#{lib.path}'" if library_mapped_to(lib.path)
|
62
|
+
@libraries << lib
|
63
|
+
return true
|
64
|
+
end
|
65
|
+
|
66
|
+
#Function used in src/confic/libraries.rb
|
67
|
+
def design_library(name, options={})
|
68
|
+
lib = Library.new(self, name, :design, options)
|
69
|
+
lib.save
|
70
|
+
lib
|
71
|
+
end
|
51
72
|
|
52
|
-
#Function used
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
73
|
+
#Function used in src/confic/libraries.rb
|
74
|
+
def testbench_library(name, options={})
|
75
|
+
lib = Library.new(self, name, :testbench, options)
|
76
|
+
lib.save
|
77
|
+
lib
|
57
78
|
end
|
58
79
|
|
59
80
|
def load_sources
|
data/lib/ecic/source_file.rb
CHANGED
@@ -0,0 +1,98 @@
|
|
1
|
+
module Ecic
|
2
|
+
#Class that can provide various info about what do to with a source file.
|
3
|
+
class SourceFileInfo
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
attr_reader :absolute_path, :library
|
8
|
+
|
9
|
+
STANDARD_LIBRARY_FOLDERS_LIST = ["src/design", "src/testbench"]
|
10
|
+
|
11
|
+
def initialize(project, file_name, library=nil)
|
12
|
+
@project = project
|
13
|
+
@absolute_path = Pathname.new(File.expand_path(file_name))
|
14
|
+
@relative_path_from_project = @absolute_path.relative_path_from(Pathname.new("#{@project.root}"))
|
15
|
+
@library = library || get_library_from_file_path
|
16
|
+
end
|
17
|
+
|
18
|
+
#TBA: Make sure this function works for libraries under src/testbench as
|
19
|
+
#well and make sure it returns nil, if the library name cannot be determined.
|
20
|
+
#TBA: Update this function to first look for any sources.rb files within the
|
21
|
+
#project folder structure.
|
22
|
+
def get_library_from_file_path
|
23
|
+
return nil if is_outside_project?
|
24
|
+
sources_file_dir = find_sources_file_dir
|
25
|
+
if sources_file_dir
|
26
|
+
#A sources.rb file was found."
|
27
|
+
#Check if an existing library is already mapped to that folder. If so, return that library
|
28
|
+
#and otherwise return a new library that is named according to the folder
|
29
|
+
already_mapped_lib = @project.library_mapped_to(sources_file_dir.to_s)
|
30
|
+
return already_mapped_lib if already_mapped_lib
|
31
|
+
#Use the name of the folder as the library name:"
|
32
|
+
lib_dir = sources_file_dir
|
33
|
+
else
|
34
|
+
# puts " #Could not find an existing sources.rb file for the given source file"
|
35
|
+
lib_dir = get_default_library_dir_from_file_path
|
36
|
+
end
|
37
|
+
unless lib_dir.nil?
|
38
|
+
lib_name = lib_dir.basename.to_s
|
39
|
+
Ecic::Library.new(@project, lib_name, get_library_type_from_file_path, :path => lib_dir)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def is_outside_project?
|
44
|
+
# @relative_path_from_project.to_s.split('/')[0] == ".."
|
45
|
+
/\A\.\./.match(@relative_path_from_project.to_s)
|
46
|
+
end
|
47
|
+
|
48
|
+
# def within_expected_folder?
|
49
|
+
# rel_design_path_list = @relative_path_from_project.to_s.split('/')
|
50
|
+
# return nil if rel_design_path_list.length < 3
|
51
|
+
# str = [rel_design_path_list.first(2)].join('/')
|
52
|
+
# STANDARD_LIBRARY_FOLDERS_LIST.include? str
|
53
|
+
# end
|
54
|
+
|
55
|
+
#Function that looks for a sources.rb file within the project
|
56
|
+
def find_sources_file_dir(dir = @relative_path_from_project.dirname)
|
57
|
+
return nil if is_outside_project?
|
58
|
+
file = File.join(@project.root, dir, "sources.rb")
|
59
|
+
if dir.root? or dir.to_s == "."
|
60
|
+
return nil
|
61
|
+
elsif File.exists?(file)
|
62
|
+
return dir
|
63
|
+
else
|
64
|
+
return find_sources_file_dir(dir.parent)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#Function that returns the name of the directory that is placed just under src/design or src/testbench:
|
69
|
+
def get_default_library_dir_from_file_path
|
70
|
+
#Get the first directory name after src/design or src/testbench:
|
71
|
+
rel_design_path_list = @relative_path_from_project.to_s.split('/')
|
72
|
+
return nil if rel_design_path_list.length < 3
|
73
|
+
return nil unless STANDARD_LIBRARY_FOLDERS_LIST.include? [rel_design_path_list.first(2)].join('/')
|
74
|
+
Pathname.new([rel_design_path_list.first(3)].join('/'))
|
75
|
+
end
|
76
|
+
|
77
|
+
#Function that returns the type of library that
|
78
|
+
def get_library_type_from_file_path
|
79
|
+
#Get the first directory name after src/design or src/testbench:
|
80
|
+
rel_design_path_list = @relative_path_from_project.to_s.split('/')
|
81
|
+
return nil if rel_design_path_list.length < 2
|
82
|
+
case [rel_design_path_list.first(2)].join('/')
|
83
|
+
when "src/testbench"
|
84
|
+
return :testbench
|
85
|
+
when "src/design"
|
86
|
+
return :design
|
87
|
+
else
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def sources_file_path
|
93
|
+
return nil if @library.nil?
|
94
|
+
# puts "#{@library.path}/sources.rb"
|
95
|
+
Pathname.new("#{@library.path}/sources.rb")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -4,21 +4,21 @@ module Ecic
|
|
4
4
|
include Thor::Actions
|
5
5
|
desc 'Generate a new SystemVerilog design'
|
6
6
|
|
7
|
-
attr_writer :
|
7
|
+
attr_writer :library, :design_name
|
8
8
|
|
9
9
|
def self.source_root
|
10
10
|
File.dirname(__FILE__) + '/../../templates/project'
|
11
11
|
end
|
12
12
|
|
13
13
|
def copy_rtl_templates
|
14
|
-
base_name = "
|
14
|
+
base_name = "#{@library.path}/#{@design_name}"
|
15
15
|
template("src/design/lib/design.sv.tt", "#{base_name}.sv")
|
16
16
|
end
|
17
17
|
|
18
18
|
def update_src_list
|
19
|
-
src_file = "
|
19
|
+
src_file = "#{@library.path}/sources.rb"
|
20
20
|
create_file src_file unless File.exists?(src_file)
|
21
|
-
append_to_file src_file, "source_file
|
21
|
+
append_to_file src_file, "source_file('#{@design_name}.sv')\n"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/lib/ecic/version.rb
CHANGED
data/lib/ecic.rb
CHANGED
@@ -28,8 +28,10 @@ module Ecic
|
|
28
28
|
autoload :SvDesignGenerator, "ecic/sv_design_generator"
|
29
29
|
autoload :ProjectGenerator, "ecic/project_generator"
|
30
30
|
autoload :LibraryGenerator, "ecic/library_generator"
|
31
|
-
autoload :
|
31
|
+
autoload :SourceListUpdater, "ecic/helpers/source_list_updater"
|
32
|
+
autoload :LibraryCreationHelper, "ecic/helpers/library_creation_helper"
|
32
33
|
autoload :SourceFile, "ecic/source_file"
|
33
34
|
autoload :Library, "ecic/library"
|
34
35
|
autoload :Project, "ecic/project"
|
35
|
-
|
36
|
+
autoload :SourceFileInfo, "ecic/source_file_info"
|
37
|
+
end
|
data/notes.txt
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
#Make sure to check if a library already is mapped to a given folder - before asking to create a new one (in case a library with different name than the folder name is already mapped to that folder)
|
2
|
+
|
3
|
+
#The 'all' option for creating a new library (when adding files) does not work
|
4
|
+
|
5
|
+
#When sources files are listed, they must be displayed in alphabetical order.
|
6
|
+
|
7
|
+
#Use "raise SystemExit" instead of the various "exit" calls
|
8
|
+
|
9
|
+
* Make sure the design_generator still works, now that the 'add_src_file' method has been changed.
|
10
|
+
|
11
|
+
* make sure "/Users/torbenj/projects/github/ecic/exe/ecic generate library dsp_core" command works
|
12
|
+
|
13
|
+
* When generating a library, the libraries.rb file must include a path as a 2nd optional option, if the design library is not placed in src/design or if a testbench library is not placed in src/testbench.
|
14
|
+
|
15
|
+
* Update the 'add_src_file' method so this method ensures that file paths are always relative to the sources.rb file.
|
16
|
+
|
17
|
+
* Consider adding support for having libraries within subfolders, ie. a
|
18
|
+
"--lib=blk1/subblock" should expect a sources.rb file in eg "src/design/blk1/subblock" and the library name should be
|
19
|
+
converted eg. "blk1-subblock" when compiling and when using it in a VHDL design.
|
20
|
+
|
21
|
+
|
22
|
+
* bug: 'addfile' command assumes that files are placed inder src/design - and never under src/testbench!! (given the fact that the --lib option is used, how can be specify a library under src/testbench ?? One option could be to require that the addfile command is called from within a library/testbench folder if adding a file not placed in either src/Design or src/testbench - and then remove the --lib option completely?) .
|
23
|
+
|
24
|
+
Same issue with 'add_src_file' which also assumes src/design folder
|
25
|
+
|
26
|
+
* ls -d */ -> returns list of directorys (but include a trailing / character)
|
27
|
+
|
1
28
|
* Remove any '/' prefix and postfix from library names when generating a new library (to allow use of "find" command to generate a number of libraries)
|
2
29
|
* 'addfile' command must check that each add file actually exists.
|
3
30
|
|
@@ -6,7 +33,4 @@
|
|
6
33
|
add design chip, :env => ['asic_rtl', 'asic_gate', 'fpga_rtl']
|
7
34
|
add design [basic_vhdl, chip], :except => {:env => ['asic']}
|
8
35
|
#add design chip_tb, :path => '/some/absolute/path'
|
9
|
-
#add testbench chip_tb, :path => '/some/absolute/path'
|
10
|
-
|
11
|
-
#Libraries can be added in libraries.rb with the syntax:
|
12
|
-
library.create('lib_x')
|
36
|
+
#add testbench chip_tb, :path => '/some/absolute/path'
|
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
#Syntax:
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# design_library('library_name')
|
6
6
|
#
|
7
|
-
# where
|
8
|
-
|
9
|
-
#Syntax:
|
7
|
+
# where library_name is the name of a VHDL/Verilog library, which is normally placed in a folder of the same name under src/design
|
10
8
|
#
|
11
|
-
#
|
9
|
+
# testbench_library('testbench_name')
|
12
10
|
#
|
13
|
-
# where
|
11
|
+
# where testbench_name is the name of a testbench library, which is normally placed in a folder of the same name under src/testbench
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ecic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Torben Fox Jacobsen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -144,12 +144,14 @@ files:
|
|
144
144
|
- lib/ecic/file_adder.rb
|
145
145
|
- lib/ecic/generate.rb
|
146
146
|
- lib/ecic/help.rb
|
147
|
-
- lib/ecic/helpers/
|
147
|
+
- lib/ecic/helpers/library_creation_helper.rb
|
148
|
+
- lib/ecic/helpers/source_list_updater.rb
|
148
149
|
- lib/ecic/library.rb
|
149
150
|
- lib/ecic/library_generator.rb
|
150
151
|
- lib/ecic/project.rb
|
151
152
|
- lib/ecic/project_generator.rb
|
152
153
|
- lib/ecic/source_file.rb
|
154
|
+
- lib/ecic/source_file_info.rb
|
153
155
|
- lib/ecic/sv_design_generator.rb
|
154
156
|
- lib/ecic/version.rb
|
155
157
|
- notes.txt
|
@@ -178,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
178
180
|
requirements:
|
179
181
|
- - ">="
|
180
182
|
- !ruby/object:Gem::Version
|
181
|
-
version:
|
183
|
+
version: 2.4.4
|
182
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
185
|
requirements:
|
184
186
|
- - ">="
|