rggen 0.4.1 → 0.4.2
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 +4 -4
- data/README.md +44 -136
- data/lib/rggen.rb +1 -0
- data/lib/rggen/base/internal_struct.rb +28 -0
- data/lib/rggen/base/item.rb +1 -0
- data/lib/rggen/builtins.rb +1 -0
- data/lib/rggen/builtins/bit_field/field_model.rb +2 -2
- data/lib/rggen/builtins/bit_field/rwl_rwe.erb +15 -0
- data/lib/rggen/builtins/bit_field/rwl_rwe.rb +55 -0
- data/lib/rggen/builtins/bit_field/type.rb +9 -0
- data/lib/rggen/builtins/register/read_data.rb +32 -11
- data/lib/rggen/builtins/register/shadow.rb +14 -14
- data/lib/rggen/core_components/register_map/bit_field_factory.rb +2 -2
- data/lib/rggen/core_components/register_map/item_factory.rb +1 -1
- data/lib/rggen/core_components/register_map/register_block_factory.rb +2 -2
- data/lib/rggen/core_components/register_map/register_factory.rb +2 -2
- data/lib/rggen/core_extensions/facets.rb +1 -0
- data/lib/rggen/input_base/component_factory.rb +4 -4
- data/lib/rggen/input_base/item.rb +1 -0
- data/lib/rggen/output_base/item.rb +1 -0
- data/lib/rggen/output_base/verilog_utility/declaration.rb +12 -21
- data/lib/rggen/version.rb +1 -1
- data/ral/rggen_ral_field_rwl_rwe.svh +158 -0
- data/ral/rggen_ral_pkg.sv +1 -0
- data/ral/rggen_ral_shadow_reg.svh +51 -46
- data/rtl/bit_field/rggen_bit_field_rwl_rwe.sv +30 -0
- data/sample/sample.csv +3 -1
- data/sample/sample.xls +0 -0
- data/sample/sample.xlsx +0 -0
- data/sample/sample_0.sv +78 -27
- data/sample/sample_0_ral_pkg.sv +16 -3
- data/sample/sample_setup.rb +1 -1
- data/setup/default.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4a6ce8cdb613957faf3d1261a338b84a8b631ac
|
4
|
+
data.tar.gz: 5cca3d0af73d1aa9d81d6eac43dc583fabb86491
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f74630a5687e2ab0f8a20ddb647726ee139dc240642c834e1826272bbb29e8b8066b5140c70b33d0cfc45a6828058aac53c51b195d8fb4af34f3078af7a6965
|
7
|
+
data.tar.gz: 1de526c92b6c4c6304bdb4d6dcb85d0487fe8c522ad25ac369178ce5901d72f13881e5285cfb443246a8353fa63e8e1eec8b0c49c9bb056cab0f55bcaa9063fb
|
data/README.md
CHANGED
@@ -1,135 +1,43 @@
|
|
1
|
-
[](https://badge.fury.io/rb/rggen)
|
2
|
-
[](https://travis-ci.org/taichi-ishitani/rggen)
|
3
|
-
[](https://codeclimate.com/github/taichi-ishitani/rggen)
|
1
|
+
[](https://badge.fury.io/rb/rggen)
|
2
|
+
[](https://travis-ci.org/taichi-ishitani/rggen)
|
3
|
+
[](https://codeclimate.com/github/taichi-ishitani/rggen)
|
4
4
|
[](https://codeclimate.com/github/taichi-ishitani/rggen/coverage)
|
5
5
|
[](https://gitter.im/taichi-ishitani/rggen?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
6
|
-
|
7
|
-
# RgGen
|
8
|
-
|
9
|
-
RgGen is a code generation tool for SoC designers.
|
10
|
-
It will automatically generate source code for control registers in a SoC design, e.g. RTL, UVM RAL model, from its register map document.
|
11
|
-
Also RgGen is customizable so you can build your specific generate tool.
|
12
|
-
|
13
|
-
## Ruby
|
14
|
-
|
15
|
-
RgGen is written in the [*Ruby*](https://www.ruby-lang.org/en/about/) programing language and supports version 2.0 or later.
|
16
|
-
If you don't have above version of Ruby, you need to install the Ruby at first.
|
17
|
-
To install the Ruby, see [this page](https://www.ruby-lang.org/en/downloads/).
|
18
|
-
|
19
|
-
## Installation
|
20
|
-
|
21
|
-
To install RgGen and required libraries, use the following command:
|
22
|
-
|
23
|
-
$ gem install rggen
|
24
|
-
|
25
|
-
RgGen will be installed under your system root.
|
26
|
-
|
27
|
-
If you want to install them on other location, you need to specify the install directory and set the **GEM_PATH** environment variable like below:
|
28
|
-
|
29
|
-
$ gem install --install-dir YOUR_INSTALL_DIRECTORY rggen
|
30
|
-
$ export GEM_PATH=YOUR_INSTALL_DIRECTORY
|
31
|
-
|
32
|
-
## Usage
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
address_width: 16
|
42
|
-
data_width: 32
|
43
|
-
host_if: apb
|
44
|
-
~~~
|
45
|
-
- JSON
|
46
|
-
~~~JSON
|
47
|
-
{
|
48
|
-
"address_width": 16,
|
49
|
-
"data_width": 32,
|
50
|
-
"host_if": "apb"
|
51
|
-
}
|
52
|
-
~~~
|
53
|
-
|
54
|
-
These attributes have default values. If you use a default value, you don't specify its value.
|
55
|
-
In addition, if you use default values for all of attributes, you don't need to write a configuration file.
|
56
|
-
|
57
|
-
### Writing Register Map Document
|
58
|
-
|
59
|
-
RgGen allows to use a spreadsheet to input the register map of your design so you can directly input your register map document to RgGen.
|
60
|
-
To do this, you need to write your register map document according to below table format.
|
61
|
-
|
62
|
-
| |A |B |C |D |E |F |G |H |I |J |K |
|
63
|
-
|:---|:---|:-------------|:------------|:--------------|:--------------------------------|:-------|:-------------|:---------|:---|:-----------|:--------|
|
64
|
-
|1 | |Block Name |block_0 | | | | | | | | |
|
65
|
-
|2 | |Byte Size |256 | | | | | | | | |
|
66
|
-
|3 | | | | | | | | | | | |
|
67
|
-
|4 | |Offset Address|Register Name|Array Dimension|Shadow Index |External|Bit Assignment|Field Name|Type|Iitial Value|Reference|
|
68
|
-
|5 | |0x00 |register_0 | | | |[31:16] |field_0_0 |rw |0 | |
|
69
|
-
|6 | | | | | | |[15:0] |field_0_1 |rw |0 | |
|
70
|
-
|7 | |0x04 |register_1 | | | |[16] |field_1_0 |rw |0 | |
|
71
|
-
|8 | | | | | | |[0] |field_1_1 |ro | | |
|
72
|
-
|9 | |0x10 - 0x1F |register_2 |[4] | | |[7:0] |field_2_0 |rw |0 | |
|
73
|
-
|10 | |0x20 - 0x3F |register_3 | | |true | | | | | |
|
74
|
-
|11 | |0x40 |register_4 |[2, 4] |field_1_0:1, field_0_0, field_0_1| |[7:0] |field_4_0 |rw |0 | |
|
75
|
-
|12 | |0x44 |register_5 | | | |[8] |field_5_0 |w0s |0 | |
|
76
|
-
|13 | | | | | | |[0] |field_5_1 |w1s |0 | |
|
77
|
-
|14 | |0x48 |register_6 | | | |[8] |field_6_0 |w0c |0 |field_1_0|
|
78
|
-
|15 | | | | | | |[0] |field_6_1 |w1c |0 |field_1_0|
|
79
|
-
|
80
|
-
By default, RgGen supports CSV, ODS, XLS and XLSX sparedsheet file types.
|
81
|
-
|
82
|
-
### Generating Source Code
|
83
|
-
|
84
|
-
To generate soruce code from your register map document, use the following command:
|
85
|
-
|
86
|
-
$ rggen your_register_map.xls
|
87
|
-
|
88
|
-
If you have a configuration file, you need to use `-c/--configuration` option:
|
89
|
-
|
90
|
-
$ rggen -c your_configuration.yml your_register_map.xls
|
91
|
-
|
92
|
-
By default, RgGen will generate RTL SV code under `rtl` directory and UVM RAL model under `ral` dicrectory.
|
93
|
-
In addition, file name of generated files is accoding to below rule.
|
94
|
-
- RTL
|
95
|
-
- `your_block_name`.sv
|
96
|
-
- RAL model
|
97
|
-
- `your_block_name`_ral_pkg.sv
|
98
|
-
|
99
|
-
### Compiling Your Design
|
100
|
-
|
101
|
-
RgGen has base RTL modules and RAL model package (the base library) to build generated RTL and UVM RAL models.
|
102
|
-
Therefore, to compile your design with the base library, you need followins steps:
|
103
|
-
|
104
|
-
1. Set the RGGEN_HOME environment variable
|
105
|
-
2. Link the base library with you design
|
106
|
-
|
107
|
-
**RGGEN_HOME** environement variable is to show the install direcoty.
|
108
|
-
To set the variable, you can use `--show-home` option like below:
|
109
|
-
|
110
|
-
$ export RGGEN_HOME=`rggen --show-home`
|
111
|
-
|
112
|
-
To link the base library with your design, RgGen has file lists for the base library.
|
113
|
-
By using the lists, you can compile your design and the base library like below:
|
114
|
-
|
115
|
-
$ simulator \
|
116
|
-
-f $RGGEN_HOME/rtl/compile.f \
|
117
|
-
-f $RGGEN_HOME/ral/compile.f \
|
118
|
-
rtl/your_register_block.sv \
|
119
|
-
ral/your_register_block_ral_pkg.sv \
|
120
|
-
your_test_bench.sv \
|
121
|
-
your_design.v
|
122
|
-
|
123
|
-
### Note
|
124
|
-
|
125
|
-
Contents of configuration file and register map document and structure of genrerated RTL and RAL model described above are default.
|
126
|
-
Also you can change these by customizing RgGen.
|
127
|
-
|
128
|
-
## Development
|
129
|
-
|
130
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
131
|
-
|
132
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
6
|
+
|
7
|
+
# RgGen
|
8
|
+
|
9
|
+
RgGen is a code generation tool for SoC designers.
|
10
|
+
It will automatically generate source code for control registers in a SoC design, e.g. RTL, UVM RAL model, from its register map document.
|
11
|
+
Also RgGen is customizable so you can build your specific generate tool.
|
12
|
+
|
13
|
+
## Ruby
|
14
|
+
|
15
|
+
RgGen is written in the [*Ruby*](https://www.ruby-lang.org/en/about/) programing language and supports version 2.0 or later.
|
16
|
+
If you don't have above version of Ruby, you need to install the Ruby at first.
|
17
|
+
To install the Ruby, see [this page](https://www.ruby-lang.org/en/downloads/).
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
To install RgGen and required libraries, use the following command:
|
22
|
+
|
23
|
+
$ gem install rggen
|
24
|
+
|
25
|
+
RgGen will be installed under your system root.
|
26
|
+
|
27
|
+
If you want to install them on other location, you need to specify the install directory and set the **GEM_PATH** environment variable like below:
|
28
|
+
|
29
|
+
$ gem install --install-dir YOUR_INSTALL_DIRECTORY rggen
|
30
|
+
$ export GEM_PATH=YOUR_INSTALL_DIRECTORY
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
See [this page](https://github.com/taichi-ishitani/rggen/wiki/Getting-Started)
|
35
|
+
|
36
|
+
## Development
|
37
|
+
|
38
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
39
|
+
|
40
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
133
41
|
|
134
42
|
## Contact
|
135
43
|
|
@@ -139,11 +47,11 @@ If you have any questions, problems, ideas or somethings, you can post them on t
|
|
139
47
|
2. [Chat room](https://gitter.im/taichi-ishitani/rggen)
|
140
48
|
3. [Mail](mailto:taichi730@gmail.com)
|
141
49
|
|
142
|
-
## Contributing
|
143
|
-
|
144
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/taichi-ishitani/rggen. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
145
|
-
|
146
|
-
## License
|
147
|
-
|
50
|
+
## Contributing
|
51
|
+
|
52
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/taichi-ishitani/rggen. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
53
|
+
|
54
|
+
## License
|
55
|
+
|
148
56
|
Copyright © 2015-2016 Taichi Ishitani.
|
149
57
|
RgGen is available as open source under the terms of [the MIT License](LICENSE.txt).
|
data/lib/rggen.rb
CHANGED
@@ -17,6 +17,7 @@ module RgGen
|
|
17
17
|
|
18
18
|
require_relative 'rggen/base/hierarchical_accessors'
|
19
19
|
require_relative 'rggen/base/hierarchical_item_accessors'
|
20
|
+
require_relative 'rggen/base/internal_struct'
|
20
21
|
require_relative 'rggen/base/component'
|
21
22
|
require_relative 'rggen/base/item'
|
22
23
|
require_relative 'rggen/base/component_factory'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RgGen
|
2
|
+
module Base
|
3
|
+
module InternalStruct
|
4
|
+
private
|
5
|
+
|
6
|
+
def internal_structs
|
7
|
+
@internal_structs ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def define_struct(struct_name, members, &body)
|
11
|
+
return if internal_structs.key?(struct_name)
|
12
|
+
internal_structs[struct_name] = Struct.new(*members, &body)
|
13
|
+
define_method(struct_name) do
|
14
|
+
self.class.send(:internal_structs)[struct_name]
|
15
|
+
end
|
16
|
+
private(struct_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def inherited(subclass)
|
20
|
+
super(subclass)
|
21
|
+
return unless instance_variable_defined?(:@internal_structs)
|
22
|
+
subclass.instance_variable_set(
|
23
|
+
:@internal_structs, Hash[@internal_structs]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/rggen/base/item.rb
CHANGED
data/lib/rggen/builtins.rb
CHANGED
@@ -14,6 +14,7 @@ require_relative 'builtins/bit_field/name'
|
|
14
14
|
require_relative 'builtins/bit_field/reference'
|
15
15
|
require_relative 'builtins/bit_field/type'
|
16
16
|
require_relative 'builtins/bit_field/rw'
|
17
|
+
require_relative 'builtins/bit_field/rwl_rwe'
|
17
18
|
require_relative 'builtins/bit_field/ro'
|
18
19
|
require_relative 'builtins/bit_field/w0c_w1c'
|
19
20
|
require_relative 'builtins/bit_field/w0s_w1s'
|
@@ -2,11 +2,11 @@ simple_item :bit_field, :field_model do
|
|
2
2
|
ral do
|
3
3
|
export :model_creation
|
4
4
|
|
5
|
-
delegate [:name, :width, :lsb, :access] => :bit_field
|
5
|
+
delegate [:name, :width, :lsb, :access, :model_name] => :bit_field
|
6
6
|
|
7
7
|
build do
|
8
8
|
variable :reg_model, :field_model,
|
9
|
-
data_type:
|
9
|
+
data_type: model_name,
|
10
10
|
name: name,
|
11
11
|
random: true
|
12
12
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
rggen_bit_field_rwl_rwe #(
|
2
|
+
.LOCK_MODE (<%= lock_mode %>),
|
3
|
+
.WIDTH (<%= width %>),
|
4
|
+
.INITIAL_VALUE (<%= initial_value %>)
|
5
|
+
) u_<%= bit_field.name %> (
|
6
|
+
.clk (<%= register_block.clock %>),
|
7
|
+
.rst_n (<%= register_block.reset %>),
|
8
|
+
.i_lock_or_enable (<%= lock_or_enable %>),
|
9
|
+
.i_command_valid (<%= register_block.host_if.command_valid %>),
|
10
|
+
.i_select (<%= register_block.register_select[index] %>),
|
11
|
+
.i_write (<%= register_block.host_if.write %>),
|
12
|
+
.i_write_data (<%= register_block.host_if.write_data[bit_field.msb, bit_field.lsb] %>),
|
13
|
+
.i_write_mask (<%= register_block.host_if.write_mask[bit_field.msb, bit_field.lsb] %>),
|
14
|
+
.o_value (<%= value[loop_variables] %>)
|
15
|
+
);
|
@@ -0,0 +1,55 @@
|
|
1
|
+
list_item :bit_field, :type, [:rwl, :rwe] do
|
2
|
+
register_map do
|
3
|
+
read_write
|
4
|
+
need_initial_value
|
5
|
+
use_reference width: 1, required: true
|
6
|
+
end
|
7
|
+
|
8
|
+
rtl do
|
9
|
+
build do
|
10
|
+
output :value_out,
|
11
|
+
name: "o_#{bit_field.name}",
|
12
|
+
width: width,
|
13
|
+
dimensions: dimensions
|
14
|
+
end
|
15
|
+
|
16
|
+
generate_code :module_item do |code|
|
17
|
+
code << assign(value_out[loop_variables], value[loop_variables]) << nl
|
18
|
+
code << process_template
|
19
|
+
end
|
20
|
+
|
21
|
+
def lock_mode
|
22
|
+
{ rwl: 1, rwe: 0 }[bit_field.type]
|
23
|
+
end
|
24
|
+
|
25
|
+
def initial_value
|
26
|
+
hex(bit_field.initial_value, width)
|
27
|
+
end
|
28
|
+
|
29
|
+
def lock_or_enable
|
30
|
+
mode_field.value
|
31
|
+
end
|
32
|
+
|
33
|
+
def mode_field
|
34
|
+
register_block.bit_fields.find do |f|
|
35
|
+
f.name == bit_field.reference.name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
ral do
|
41
|
+
model_name { "#{class_name}#(#{mode_register}, #{mode_field})" }
|
42
|
+
|
43
|
+
def class_name
|
44
|
+
"rggen_ral_field_#{bit_field.type}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def mode_register
|
48
|
+
string(bit_field.reference.register.name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def mode_field
|
52
|
+
string(bit_field.reference.name)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -193,11 +193,16 @@ list_item :bit_field, :type do
|
|
193
193
|
ral do
|
194
194
|
item_base do
|
195
195
|
export :access
|
196
|
+
export :model_name
|
196
197
|
export :hdl_path
|
197
198
|
|
198
199
|
define_helpers do
|
199
200
|
attr_setter :access
|
200
201
|
|
202
|
+
def model_name(&body)
|
203
|
+
define_method(:model_name, &body)
|
204
|
+
end
|
205
|
+
|
201
206
|
def hdl_path(&body)
|
202
207
|
define_method(:hdl_path, &body)
|
203
208
|
end
|
@@ -207,6 +212,10 @@ list_item :bit_field, :type do
|
|
207
212
|
string((self.class.access || bit_field.type).to_s.upcase)
|
208
213
|
end
|
209
214
|
|
215
|
+
def model_name
|
216
|
+
:rggen_ral_field
|
217
|
+
end
|
218
|
+
|
210
219
|
def hdl_path
|
211
220
|
"u_#{bit_field.name}.value"
|
212
221
|
end
|
@@ -1,13 +1,23 @@
|
|
1
1
|
simple_item :register, :read_data do
|
2
2
|
rtl do
|
3
|
-
available?
|
4
|
-
!register.external?
|
5
|
-
end
|
3
|
+
available? { register.internal? }
|
6
4
|
|
7
5
|
generate_code :module_item do |buffer|
|
8
6
|
buffer << assign(register_read_data, read_data) << nl
|
9
7
|
end
|
10
8
|
|
9
|
+
define_struct :read_data_entry, [:lsb, :msb, :value, :dummy] do
|
10
|
+
def initialize(args)
|
11
|
+
self.lsb = args[:lsb]
|
12
|
+
self.msb = args[:msb]
|
13
|
+
self.value = args[:value]
|
14
|
+
self.dummy = args[:dummy] || false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
delegate [:data_width] => :configuration
|
19
|
+
delegate [:loop_variables] => :register
|
20
|
+
|
11
21
|
def register_read_data
|
12
22
|
register_block.register_read_data[register.index]
|
13
23
|
end
|
@@ -21,16 +31,27 @@ simple_item :register, :read_data do
|
|
21
31
|
end
|
22
32
|
|
23
33
|
def read_data_expressions
|
24
|
-
|
25
|
-
|
26
|
-
readable_fields.each do |field|
|
27
|
-
padding_bits = last_lsb - field.msb - 1
|
28
|
-
last_lsb = field.lsb
|
34
|
+
read_data_entries.each_cons(2).with_object([]) do |entries, expressions|
|
35
|
+
padding_bits = entries[0].lsb - entries[1].msb - 1
|
29
36
|
expressions << hex(0, padding_bits) if padding_bits > 0
|
30
|
-
expressions <<
|
37
|
+
expressions << entries[1].value unless entries[1].dummy
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def read_data_entries
|
42
|
+
[].tap do |entries|
|
43
|
+
entries << read_data_entry.new(lsb: data_width, dummy: true)
|
44
|
+
entries.concat(readable_field_entries)
|
45
|
+
entries << read_data_entry.new(msb: -1, dummy: true)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def readable_field_entries
|
50
|
+
readable_fields.map do |field|
|
51
|
+
read_data_entry.new(
|
52
|
+
lsb: field.lsb, msb: field.msb, value: field.value[loop_variables]
|
53
|
+
)
|
31
54
|
end
|
32
|
-
expressions << hex(0, last_lsb) if last_lsb > 0
|
33
|
-
expressions
|
34
55
|
end
|
35
56
|
|
36
57
|
def readable_fields
|
@@ -1,18 +1,5 @@
|
|
1
1
|
simple_item :register, :shadow do
|
2
2
|
register_map do
|
3
|
-
ShadowIndexEntry = Struct.new(:name, :value) do
|
4
|
-
def initialize(name, value)
|
5
|
-
self.name = name
|
6
|
-
self.value = value && Integer(value)
|
7
|
-
end
|
8
|
-
|
9
|
-
def ==(other)
|
10
|
-
return false unless name == other.name
|
11
|
-
return true if [value, other.value].any?(&:nil?)
|
12
|
-
value == other.value
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
3
|
field :shadow?
|
17
4
|
field :shadow_indexes
|
18
5
|
|
@@ -32,11 +19,24 @@ simple_item :register, :shadow do
|
|
32
19
|
check_specific_value_index_values
|
33
20
|
end
|
34
21
|
|
22
|
+
define_struct :shadow_index_entry, [:name, :value] do
|
23
|
+
def initialize(name, value)
|
24
|
+
self.name = name
|
25
|
+
self.value = value && Integer(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
return false unless name == other.name
|
30
|
+
return true if [value, other.value].any?(&:nil?)
|
31
|
+
value == other.value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
35
|
def parse_shadow_indexes(cell)
|
36
36
|
return nil if cell.nil? || cell.empty?
|
37
37
|
cell.split(/[,\n]/).map do |entry|
|
38
38
|
if pattern_match(entry)
|
39
|
-
|
39
|
+
shadow_index_entry.new(captures[0], captures[1])
|
40
40
|
else
|
41
41
|
error "invalid value for shadow index: #{cell.inspect}"
|
42
42
|
end
|