gupl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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