gupl 0.0.1

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.
data/lib/gupl.rb ADDED
@@ -0,0 +1,794 @@
1
+ require 'stringio'
2
+ require "gupl/version"
3
+
4
+ module Gupl
5
+
6
+ class LocalSignal
7
+
8
+ def initialize(name:, width:)
9
+ @name = name
10
+ @width = width.to_i
11
+ @type = "std_logic_vector"
12
+ end
13
+ attr_reader :name, :width
14
+
15
+ def generate_define(buf)
16
+ if @width > 0 then
17
+ buf.puts(" signal #{@name} : #{@type}(#{@width}-1 downto 0);")
18
+ else
19
+ buf.puts(" signal #{@name} : std_logic;")
20
+ end
21
+ end
22
+
23
+ def set_type(type)
24
+ @type = type
25
+ end
26
+
27
+ end
28
+
29
+ class GenericPort
30
+
31
+ def initialize(name:, width:, dir:)
32
+ @name = name
33
+ @width = width.to_i
34
+ @dir = dir
35
+ end
36
+ attr_reader :name, :width, :dir
37
+
38
+ def generate_define(buf)
39
+ if @width > 0 then
40
+ buf.puts(" #{@name} : #{@dir} std_logic_vector(#{@width}-1 downto 0);")
41
+ else
42
+ buf.puts(" #{@name} : #{@dir} std_logic;")
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ class UPLVariable
49
+ def initialize(upl, name, pos, bits)
50
+ @upl = upl
51
+ @name = name
52
+ @pos = pos
53
+ if bits[0] == '<' then
54
+ @storage = true
55
+ @bits = bits[1..].to_i
56
+ else
57
+ @storage = false
58
+ @bits = bits.to_i
59
+ end
60
+ @signals = []
61
+ if @storage then
62
+ @signals << LocalSignal.new(name: "#{@name}_waddr", width: 32)
63
+ @signals << LocalSignal.new(name: "#{@name}_we", width: 1)
64
+ @signals << LocalSignal.new(name: "#{@name}_din", width: @upl.width)
65
+ @signals << LocalSignal.new(name: "#{@name}_raddr", width: 32)
66
+ @signals << LocalSignal.new(name: "#{@name}_dout", width: @upl.width)
67
+ @signals << LocalSignal.new(name: "#{@name}_send_words", width: 32)
68
+ @signals << LocalSignal.new(name: "#{@name}_recv_words", width: 32)
69
+ else
70
+ @signals << LocalSignal.new(name: "#{@name}", width: bits)
71
+ end
72
+ end
73
+ attr_reader :name, :pos, :bits, :upl
74
+
75
+ def generate_define(buf)
76
+ @signals.each{|signal|
77
+ signal.generate_define(buf)
78
+ }
79
+ end
80
+
81
+ def storage?()
82
+ return @storage
83
+ end
84
+
85
+ end
86
+
87
+ class UPL
88
+ def initialize(entity:, name:, width:, id:)
89
+ @entity = entity
90
+ @name = name
91
+ @width = width.to_i
92
+ @id = id.to_i
93
+ @variables = []
94
+ @variable_ptr = 0
95
+ @stages = []
96
+ @storage = nil
97
+ end
98
+ attr_reader :id, :name, :width
99
+ attr_reader :data, :enable, :ack, :request
100
+ attr_reader :variables, :stages
101
+
102
+ def add_variable(name, bits)
103
+ variable = UPLVariable.new(self, name, @variable_ptr, bits)
104
+ @variables << variable
105
+ if (@variable_ptr / @width) > (@stages.size - 1) then
106
+ @stages << [variable]
107
+ else
108
+ @stages[-1] << variable
109
+ end
110
+ @variable_ptr += variable.bits
111
+ if variable.storage?
112
+ @storage = variable
113
+ end
114
+ end
115
+
116
+ def generate_ports(buf)
117
+ buf.puts(" -- #{@name}")
118
+ @data.generate_define(buf)
119
+ @enable.generate_define(buf)
120
+ @request.generate_define(buf)
121
+ @ack.generate_define(buf)
122
+ buf.puts("")
123
+ end
124
+
125
+ end
126
+
127
+ class RecvUPL < UPL
128
+
129
+ def initialize(entity:, name:, width:, id:)
130
+ super(entity: entity, name: name, width: width, id: id)
131
+ @data = GenericPort.new(name: "UPL_#{@name}_data", width: @width, dir: "in")
132
+ @enable = GenericPort.new(name: "UPL_#{@name}_en", width: 0, dir: "in")
133
+ @request = GenericPort.new(name: "UPL_#{@name}_req", width: 0, dir: "in")
134
+ @ack = GenericPort.new(name: "UPL_#{@name}_ack", width: 0, dir: "out")
135
+ end
136
+
137
+ def generate_stages(buf)
138
+ t = " " * 8
139
+ @stages.each_with_index{|stage, i|
140
+ buf.puts("#{t}when #{name}_recv_#{i} =>")
141
+ pos = @width
142
+ if i == 0 then
143
+ buf.puts("#{t} if #{enable.name} = '1' then")
144
+ buf.puts("#{t} #{@ack.name} <= '0';")
145
+ buf.puts("#{t} else")
146
+ buf.puts("#{t} #{@ack.name} <= '1';")
147
+ buf.puts("#{t} end if;")
148
+ else
149
+ buf.puts("#{t} #{@ack.name} <= '0';")
150
+ end
151
+ stage.each_with_index{|variable|
152
+ if variable.storage? then
153
+ buf.puts("#{t} if #{enable.name} = '1' then")
154
+ buf.puts("#{t} #{variable.name}_waddr <= std_logic_vector(unsigned(#{variable.name}_waddr)+1);")
155
+ buf.puts("#{t} #{variable.name}_we <= \"1\";")
156
+ buf.puts("#{t} #{variable.name}_din <= #{@data.name};")
157
+ buf.puts("#{t} #{variable.name}_recv_words <= std_logic_vector(unsigned(#{variable.name}_recv_words)+1);")
158
+ buf.puts("#{t} else")
159
+ buf.puts("#{t} #{variable.name}_we <= \"0\";")
160
+ buf.puts("#{t} end if;")
161
+ else
162
+ buf.puts("#{t} #{variable.name} <= #{@data.name}(#{pos-1} downto #{pos-variable.bits});")
163
+ pos -= variable.bits
164
+ end
165
+ }
166
+
167
+ if i == 0 then
168
+ buf.puts("#{t} if #{enable.name} = '1' then")
169
+ t += " "
170
+ end
171
+
172
+ buf.puts("#{t} #{@entity.process.statemachine.name} <= #{name}_recv_#{i+1};")
173
+
174
+ if i == 0 then
175
+ t = t[2..]
176
+ buf.puts("#{t} end if;")
177
+ end
178
+ }
179
+ buf.puts("#{t}when #{name}_recv_#{stages.size} =>")
180
+ buf.puts("#{t} if #{@enable.name} = '0' then")
181
+ buf.puts("#{t} #{@entity.process.statemachine.name} <= #{@entity.process.statemachine.name}_next;")
182
+ if @storage != nil then
183
+ buf.puts("#{t} #{@storage.name}_we <= \"0\";")
184
+ buf.puts("#{t} else")
185
+ buf.puts("#{t} #{@storage.name}_waddr <= std_logic_vector(unsigned(#{@storage.name}_waddr)+1);")
186
+ buf.puts("#{t} #{@storage.name}_we <= \"1\";")
187
+ buf.puts("#{t} #{@storage.name}_din <= #{@data.name};")
188
+ buf.puts("#{t} #{@storage.name}_recv_words <= std_logic_vector(unsigned(#{@storage.name}_recv_words)+1);")
189
+ end
190
+ buf.puts("#{t} end if;")
191
+ end
192
+
193
+ end
194
+
195
+ class SendUPL < UPL
196
+
197
+ def initialize(entity:, name:, width:, id:)
198
+ super(entity: entity, name: name, width: width, id: id)
199
+ @data = GenericPort.new(name: "UPL_#{@name}_data", width: @width, dir: "out")
200
+ @enable = GenericPort.new(name: "UPL_#{@name}_en", width: 0, dir: "out")
201
+ @request = GenericPort.new(name: "UPL_#{@name}_req", width: 0, dir: "out")
202
+ @ack = GenericPort.new(name: "UPL_#{@name}_ack", width: 0, dir: "in")
203
+ end
204
+
205
+ def generate_stages(buf)
206
+ buf.puts(" when #{name}_send_0 =>")
207
+ buf.puts(" #{@request.name} <= '1';")
208
+ if @storage != nil then
209
+ buf.puts(" #{@storage.name}_send_words <= (others => '0');")
210
+ end
211
+ buf.puts(" if #{@ack.name} = '1' then")
212
+ if @storage != nil then
213
+ buf.puts(" #{@storage.name}_raddr <= (others => '0'); -- for next next")
214
+ end
215
+ buf.puts(" #{@entity.process.statemachine.name} <= #{name}_send_1;")
216
+ buf.puts(" end if;")
217
+
218
+ buf.puts(" when #{name}_send_1 =>")
219
+ buf.puts(" #{@entity.process.statemachine.name} <= #{name}_send_2;")
220
+ if @storage != nil and @stages[0][0] == @storage then
221
+ buf.puts(" #{@storage.name}_raddr <= std_logic_vector(unsigned(#{@storage.name}_raddr)+1);")
222
+ end
223
+
224
+ @stages.each_with_index{|stage, i|
225
+ buf.puts(" when #{name}_send_#{i+2} =>")
226
+ pos = @width
227
+ state_trans = false
228
+ buf.puts(" #{@request.name} <= '0';")
229
+ stage.each{|variable|
230
+ if variable.storage? then
231
+ state_trans = true
232
+ buf.puts(" if #{variable.name}_recv_words = #{variable.name}_send_words then")
233
+ buf.puts(" #{@entity.process.statemachine.name} <= #{@entity.process.statemachine.name}_next;")
234
+ buf.puts(" #{@enable.name} <= '0';")
235
+ buf.puts(" else")
236
+ buf.puts(" #{variable.name}_raddr <= std_logic_vector(unsigned(#{variable.name}_raddr)+1); -- for next next")
237
+ buf.puts(" #{@data.name} <= #{variable.name}_dout;")
238
+ buf.puts(" #{variable.name}_send_words <= std_logic_vector(unsigned(#{variable.name}_send_words)+1);")
239
+ buf.puts(" #{@enable.name} <= '1';")
240
+ buf.puts(" end if;")
241
+ else
242
+ buf.puts(" #{@data.name}(#{pos-1} downto #{pos-variable.bits}) <= #{variable.name};")
243
+ pos -= variable.bits
244
+ end
245
+ }
246
+ if @storage != nil and @stages[i+1] != nil and @stages[i+1][0] == @storage then
247
+ buf.puts(" #{@storage.name}_raddr <= std_logic_vector(unsigned(#{@storage.name}_raddr)+1); -- for next next")
248
+ end
249
+ if state_trans == false
250
+ buf.puts(" #{@enable.name} <= '1';")
251
+ if i == stages.size - 1 then
252
+ buf.puts(" #{@entity.process.statemachine.name} <= #{@entity.process.statemachine.name}_next;")
253
+ else
254
+ buf.puts(" #{@entity.process.statemachine.name} <= #{name}_send_#{i+2+1};")
255
+ end
256
+ end
257
+ }
258
+ end
259
+
260
+ end
261
+
262
+ class State
263
+
264
+ def initialize(statemachine, name)
265
+ @statemachine = statemachine
266
+ @name = name
267
+ @contents = ""
268
+ end
269
+ attr_reader :name
270
+
271
+ def add_contents(str)
272
+ @contents += str
273
+ end
274
+
275
+ def generate(buf)
276
+ if @contents == "" then
277
+ buf.puts(" pass;")
278
+ else
279
+ buf.puts(@contents)
280
+ end
281
+ end
282
+
283
+ end
284
+
285
+
286
+ class StateMachine
287
+
288
+ def initialize(process, name)
289
+ @process = process
290
+ @name = name
291
+ @idle_state = State.new(self, "IDLE")
292
+ @states = [@idle_state]
293
+ end
294
+ attr_reader :name
295
+
296
+ def init_storage(buf)
297
+ table = {}
298
+ @process.entity.send_upls.each{|upl|
299
+ upl.variables.each{|var|
300
+ if var.storage? and table[var.name] == nil then
301
+ table[var.name] = true
302
+ buf.puts(" #{var.name}_we <= (others => '0');")
303
+ buf.puts(" #{var.name}_waddr <= (others => '1');")
304
+ buf.puts(" #{var.name}_raddr <= (others => '0');")
305
+ buf.puts(" #{var.name}_recv_words <= (others => '0');")
306
+ buf.puts(" #{var.name}_send_words <= (others => '0');")
307
+ end
308
+ }
309
+ }
310
+ @process.entity.recv_upls.each{|upl|
311
+ upl.variables.each{|var|
312
+ if var.storage? and table[var.name] == nil then
313
+ table[var.name] = true
314
+ buf.puts(" #{var.name}_we <= (others => '0');")
315
+ buf.puts(" #{var.name}_waddr <= (others => '1');")
316
+ buf.puts(" #{var.name}_raddr <= (others => '0');")
317
+ buf.puts(" #{var.name}_recv_words <= (others => '0');")
318
+ buf.puts(" #{var.name}_send_words <= (others => '0');")
319
+ end
320
+ }
321
+ }
322
+ end
323
+
324
+ def init_idle_state
325
+ upl = @process.entity.get_main_recv_upl
326
+ if upl != nil
327
+ buf = StringIO.new("", "w")
328
+ buf.puts(" #{name} <= #{upl.name}_recv_0;")
329
+ buf.puts(" #{name}_next <= #{@process.entity.name};")
330
+ @process.entity.send_upls.each{|upl|
331
+ buf.puts(" #{upl.enable.name} <= '0';")
332
+ buf.puts(" #{upl.request.name} <= '0';")
333
+ buf.puts(" #{upl.data.name} <= (others => '0');")
334
+ }
335
+ @process.entity.recv_upls.each{|upl|
336
+ buf.puts(" #{upl.ack.name} <= '0';")
337
+ }
338
+ init_storage(buf)
339
+ @idle_state.add_contents(buf.string)
340
+ end
341
+ end
342
+
343
+ def generate(buf)
344
+ init_idle_state()
345
+ buf.puts(" case #{@name} is")
346
+ @states.each{|state|
347
+ buf.puts(" when #{state.name} =>")
348
+ state.generate(buf)
349
+ }
350
+ @process.entity.send_upls.each{|upl|
351
+ upl.generate_stages(buf)
352
+ }
353
+ @process.entity.recv_upls.each{|upl|
354
+ upl.generate_stages(buf)
355
+ }
356
+ buf.puts(" when others => #{@name} <= IDLE;")
357
+ buf.puts(" end case;")
358
+ end
359
+
360
+ def add_idle_stage(str)
361
+ @idle_state.add_contents(str)
362
+ end
363
+
364
+ def add_new_stage(name)
365
+ state = State.new(self, name)
366
+ @states << state
367
+ return state
368
+ end
369
+
370
+ def generate_define(buf)
371
+ buf.puts(" -- statemachine type and signal")
372
+ sep = ""
373
+ buf.puts(" type StateType is (")
374
+ @states.each{|state|
375
+ buf.print("#{sep} #{state.name}")
376
+ sep = ",\n"
377
+ }
378
+ @process.entity.send_upls.each{|upl|
379
+ (upl.stages.size+2).times{|i|
380
+ buf.print("#{sep} #{upl.name}_send_#{i}")
381
+ sep = ",\n"
382
+ }
383
+ }
384
+ @process.entity.recv_upls.each{|upl|
385
+ (upl.stages.size+1).times{|i|
386
+ buf.print("#{sep} #{upl.name}_recv_#{i}")
387
+ sep = ",\n"
388
+ }
389
+ }
390
+ buf.puts("\n );")
391
+ buf.puts(" signal #{@name} : StateType := IDLE;")
392
+ buf.puts(" signal #{@name}_next : StateType := IDLE;")
393
+ end
394
+
395
+ end
396
+
397
+
398
+ class MainProcess
399
+
400
+ def initialize(entity)
401
+ @entity = entity
402
+ @reset_stage = nil
403
+ @statemachine = StateMachine.new(self, "gupl_state")
404
+ end
405
+ attr_reader :entity, :statemachine
406
+
407
+ def add_reset_stage(str)
408
+ @reset_stage = str
409
+ end
410
+
411
+ def add_idle_stage(str)
412
+ @statemachine.add_idle_stage(str)
413
+ end
414
+
415
+ def add_new_stage(name)
416
+ @statemachine.add_new_stage(name)
417
+ end
418
+
419
+ def generate_reset(buf)
420
+ @entity.send_upls.each{|upl|
421
+ buf.puts(" #{upl.enable.name} <= '0';")
422
+ buf.puts(" #{upl.request.name} <= '0';")
423
+ buf.puts(" #{upl.data.name} <= (others => '0');")
424
+ }
425
+ @entity.recv_upls.each{|upl|
426
+ buf.puts(" #{upl.ack.name} <= '0';")
427
+ }
428
+ buf.puts(" #{@statemachine.name} <= IDLE;")
429
+ buf.puts(" #{@entity.process.statemachine.name}_next <= IDLE;")
430
+ if @reset_stage != nil then
431
+ buf.puts("")
432
+ buf.puts(" -- user-defiend reset stage")
433
+ buf.puts(@reset_stage)
434
+ buf.puts("")
435
+ end
436
+ end
437
+
438
+ def generate(buf)
439
+ buf.puts("process(clk)")
440
+ buf.puts("begin")
441
+ buf.puts(" if rising_edge(clk) then")
442
+ buf.puts(" if reset = '1' then")
443
+ generate_reset(buf)
444
+ buf.puts(" else")
445
+ @statemachine.generate(buf)
446
+ buf.puts(" end if;")
447
+ buf.puts(" end if;")
448
+ buf.puts("end process;")
449
+ end
450
+
451
+ end
452
+
453
+ class Entity
454
+
455
+ def initialize(name)
456
+ @name = name
457
+ @send_upls = []
458
+ @recv_upls = []
459
+ @ports = []
460
+ @signals = []
461
+ @process = MainProcess.new(self)
462
+ @async = ""
463
+ end
464
+ attr_reader :name, :send_upls, :recv_upls, :process
465
+
466
+ def get_main_recv_upl()
467
+ @recv_upls.each{|upl|
468
+ return upl if upl.id == 0
469
+ }
470
+ return nil
471
+ end
472
+
473
+ def add_send_upl(upl)
474
+ @send_upls << upl
475
+ end
476
+
477
+ def add_recv_upl(upl)
478
+ @recv_upls << upl
479
+ end
480
+
481
+ def add_port(port)
482
+ @ports << port
483
+ end
484
+
485
+ def add_signal(signal)
486
+ @signals << signal
487
+ end
488
+
489
+ def add_reset_stage(str)
490
+ @process.add_reset_stage(str)
491
+ end
492
+
493
+ def add_idle_stage(str)
494
+ @process.add_idle_stage(str)
495
+ end
496
+
497
+ def add_new_stage(name)
498
+ @process.add_new_stage(name)
499
+ end
500
+
501
+ def add_async(str)
502
+ @async += str
503
+ end
504
+
505
+ def generate_vhdl_header(buf)
506
+ buf.puts("library ieee;")
507
+ buf.puts("use ieee.std_logic_1164.all;")
508
+ buf.puts("use ieee.numeric_std.all;")
509
+ buf.puts("")
510
+ end
511
+
512
+ def generate_entity_define(buf)
513
+ buf.puts("entity #{@name} is")
514
+ buf.puts("port(")
515
+
516
+ @recv_upls.each{|upl|
517
+ upl.generate_ports(buf)
518
+ }
519
+
520
+ @send_upls.each{|upl|
521
+ upl.generate_ports(buf)
522
+ }
523
+
524
+ buf.puts(" -- user-defiend ports")
525
+ @ports.each{|port|
526
+ port.generate_define(buf)
527
+ }
528
+ buf.puts("")
529
+
530
+ buf.puts(" -- system clock and reset")
531
+ buf.puts(" clk : in std_logic;")
532
+ buf.puts(" reset : in std_logic")
533
+ buf.puts(");")
534
+ buf.puts("end entity #{@name};")
535
+ buf.puts("")
536
+ end
537
+
538
+ def generate_architecture_define(buf)
539
+ buf.puts("architecture RTL of #{@name} is")
540
+ buf.puts("")
541
+
542
+ @process.statemachine.generate_define(buf)
543
+
544
+ buf.puts()
545
+ buf.puts(" -- UPL signals")
546
+ table = {}
547
+ @send_upls.each{|upl|
548
+ upl.variables.each{|var|
549
+ next if table[var.name] != nil
550
+ table[var.name] = var
551
+ var.generate_define(buf)
552
+ }
553
+ }
554
+ @recv_upls.each{|upl|
555
+ upl.variables.each{|var|
556
+ next if table[var.name] != nil
557
+ table[var.name] = var
558
+ var.generate_define(buf)
559
+ }
560
+ }
561
+
562
+ buf.puts()
563
+ buf.puts(" -- user-defiend signals")
564
+ @signals.each{|signal|
565
+ signal.generate_define(buf)
566
+ }
567
+ buf.puts("")
568
+
569
+ buf.puts(" -- ip-cores")
570
+ simple_dualportram = false
571
+ table.values.each{|var|
572
+ if var.storage? and simple_dualportram == false then
573
+ simple_dualportram = true
574
+ buf.puts(" component simple_dualportram")
575
+ buf.puts(" generic (")
576
+ buf.puts(" DEPTH : integer := 10;")
577
+ buf.puts(" WIDTH : integer := 32;")
578
+ buf.puts(" WORDS : integer := 1024")
579
+ buf.puts(" );")
580
+ buf.puts(" port (")
581
+ buf.puts(" clk : in std_logic;")
582
+ buf.puts(" reset : in std_logic;")
583
+ buf.puts(" we : in std_logic_vector(0 downto 0);")
584
+ buf.puts(" raddr : in std_logic_vector(31 downto 0);")
585
+ buf.puts(" waddr : in std_logic_vector(31 downto 0);")
586
+ buf.puts(" dout : out std_logic_vector(WIDTH-1 downto 0);")
587
+ buf.puts(" din : in std_logic_vector(WIDTH-1 downto 0);")
588
+ buf.puts(" length : out std_logic_vector(31 downto 0)")
589
+ buf.puts(" );")
590
+ buf.puts(" end component simple_dualportram;")
591
+ end
592
+ }
593
+ buf.puts("")
594
+
595
+ buf.puts("begin")
596
+ buf.puts("")
597
+ buf.puts(" -- add async")
598
+ buf.puts(@async)
599
+
600
+ buf.puts("")
601
+ @process.generate(buf)
602
+ buf.puts("")
603
+
604
+ buf.puts("")
605
+ table.values.each{|var|
606
+ if var.storage? then
607
+ buf.puts(" buf_#{var.name}_i : simple_dualportram")
608
+ buf.puts(" generic map(")
609
+ buf.puts(" DEPTH => #{Math.log2((var.bits/var.upl.width).ceil).ceil},")
610
+ buf.puts(" WIDTH => #{var.upl.width},")
611
+ buf.puts(" WORDS => #{(var.bits/var.upl.width).ceil}")
612
+ buf.puts(" )")
613
+ buf.puts(" port map(")
614
+ buf.puts(" clk => clk,")
615
+ buf.puts(" reset => reset,")
616
+ buf.puts(" we => #{var.name}_we,")
617
+ buf.puts(" raddr => #{var.name}_raddr,")
618
+ buf.puts(" waddr => #{var.name}_waddr,")
619
+ buf.puts(" dout => #{var.name}_dout,")
620
+ buf.puts(" din => #{var.name}_din,")
621
+ buf.puts(" length => open")
622
+ buf.puts(" );")
623
+ end
624
+ }
625
+
626
+
627
+ buf.puts("end RTL;")
628
+ end
629
+
630
+ def generate(buf)
631
+ buf.puts("--")
632
+ buf.puts("-- generated by gupl ver.#{VERSION}")
633
+ buf.puts("-- https://github.com/e-trees/gupl")
634
+ buf.puts("--")
635
+ buf.puts("")
636
+ generate_vhdl_header(buf)
637
+ generate_entity_define(buf)
638
+ generate_architecture_define(buf)
639
+ end
640
+
641
+ end
642
+
643
+ def self.parse_ports(reader, entity)
644
+
645
+ while line = reader.gets
646
+ l = line.strip
647
+ if /@END/i =~ l then
648
+ return
649
+ else
650
+ items = l.split(/\s*,\s*/)
651
+ port = GenericPort.new(name: items[0], dir: items[2], width: items[1])
652
+ entity.add_port(port)
653
+ end
654
+ end
655
+
656
+ end
657
+
658
+ def self.parse_signals(reader, entity)
659
+
660
+ while line = reader.gets
661
+ l = line.strip
662
+ if /@END/i =~ l then
663
+ return
664
+ else
665
+ items = l.split(/\s*,\s*/)
666
+ signal = LocalSignal.new(name: items[0], width: items[1])
667
+ if items.size > 2 then
668
+ signal.set_type(items[2])
669
+ end
670
+ entity.add_signal(signal)
671
+ end
672
+ end
673
+
674
+ end
675
+
676
+ def self.parse_reset_stage(reader, entity)
677
+ str = ""
678
+ while line = reader.gets
679
+ l = line.strip
680
+ if /@END/i =~ l then
681
+ break
682
+ else
683
+ str += line
684
+ end
685
+ end
686
+ entity.add_reset_stage(str)
687
+ end
688
+
689
+ def self. parse_idle_stage(reader, entity)
690
+ str = ""
691
+ while line = reader.gets
692
+ l = line.strip
693
+ if /@END/i =~ l then
694
+ break
695
+ else
696
+ str += line
697
+ end
698
+ end
699
+ entity.add_idle_stage(str)
700
+ end
701
+
702
+ def self.parse_stage(reader, entity, name)
703
+ stage = entity.add_new_stage(name)
704
+
705
+ str = ""
706
+ while line = reader.gets
707
+ l = line.strip
708
+ if /@END/i =~ l then
709
+ break
710
+ elsif /^@TO\s+(\w+)/i =~ l then
711
+ str += " #{entity.process.statemachine.name} <= #{$1};\n"
712
+ elsif /^@SEND\s+(\w+)/i =~ l then
713
+ str += " #{entity.process.statemachine.name} <= #{$1}_send_0;\n"
714
+ str += " #{entity.process.statemachine.name}_next <= IDLE;\n"
715
+ elsif /^@SEND\s+(\w+)\s+@TO\s+(\w+)/i =~ l then
716
+ str += " #{entity.process.statemachine.name} <= #{$1}_send_0;\n"
717
+ str += " #{entity.process.statemachine.name}_next <= #{$2};\n"
718
+ elsif /^@RECV\s+(\w+)\s+@TO\s+(\w+)/i =~ l then
719
+ str += " #{entity.process.statemachine.name} <= #{$1}_recv_0;\n"
720
+ str += " #{entity.process.statemachine.name}_next <= #{$2};\n"
721
+ else
722
+ str += line
723
+ end
724
+ end
725
+
726
+ stage.add_contents(str)
727
+ end
728
+
729
+ def self.parse_upl(reader, upl)
730
+ str = ""
731
+ while line = reader.gets
732
+ l = line.strip
733
+ if /@END/i =~ l then
734
+ return
735
+ else
736
+ items = l.split(/\s*,\s*/)
737
+ upl.add_variable(items[0], items[1])
738
+ end
739
+ end
740
+ end
741
+
742
+ def self.parse_async(reader,entity)
743
+ str = ""
744
+ while line = reader.gets
745
+ l = line.strip
746
+ if /@END/i =~ l then
747
+ break
748
+ else
749
+ str += line
750
+ end
751
+ end
752
+ entity.add_async(str)
753
+ end
754
+
755
+ def self.main(str)
756
+ entity = nil
757
+ reader = StringIO.new(str, "r")
758
+ version = nil
759
+
760
+ while line = reader.gets
761
+ l = line.strip
762
+ if /@GUPL_VERSION\s+(\w+)/i =~ l then
763
+ version = $1
764
+ elsif /@ENTITY\s+(\w+)/i =~ l then
765
+ entity = Entity.new($1)
766
+ elsif /@RECV\s+(\d+)\s+(\w+)\s+(\d+)/i =~ l then
767
+ upl = RecvUPL.new(entity: entity, name: $2, width: $3.to_i, id: $1.to_i)
768
+ entity.add_recv_upl(upl)
769
+ parse_upl(reader, upl)
770
+ elsif /@SEND\s+(\d+)\s+(\w+)\s+(\d+)/i =~ l then
771
+ upl = SendUPL.new(entity: entity, name: $2, width: $3.to_i, id: $1.to_i)
772
+ entity.add_send_upl(upl)
773
+ parse_upl(reader, upl)
774
+ elsif /@PORT/i =~ l then
775
+ parse_ports(reader, entity)
776
+ elsif /@LOCAL/i =~ l then
777
+ parse_signals(reader, entity)
778
+ elsif /@RESET_STAGE/i =~ l then
779
+ parse_reset_stage(reader, entity)
780
+ elsif /@IDLE_STAGE/i =~ l then
781
+ parse_idle_stage(reader, entity)
782
+ elsif /@STAGE\s+(\w+)/i =~ l then
783
+ parse_stage(reader, entity, $1)
784
+ elsif /@ASYNC/i =~ l then
785
+ parse_async(reader, entity)
786
+ end
787
+ end
788
+
789
+ puts "ERROR: entity is undefined" if entity == nil
790
+ puts "ERROR: version is undefined" if version == nil
791
+ return version, entity
792
+ end
793
+
794
+ end