OpenCores
URL https://opencores.org/ocsvn/tcp_socket/tcp_socket/trunk

Subversion Repositories tcp_socket

[/] [tcp_socket/] [trunk/] [chips2/] [chips/] [compiler/] [verilog_speed.py] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jondawson
#!/usr/bin/env python
2
"""A C to Verilog compiler"""
3
 
4
__author__ = "Jon Dawson"
5
__copyright__ = "Copyright (C) 2013, Jonathan P Dawson"
6
__version__ = "0.1"
7
 
8
def unique(l):
9
 
10
  """In the absence of set in older python implementations, make list values unique"""
11
 
12
  return dict(zip(l, l)).keys()
13
 
14
def log2(frames):
15
 
16
  """Integer only algorithm to calculate the number of bits needed to store a number"""
17
 
18
  bits = 1
19
  power = 2
20
  while power < frames:
21
      bits += 1
22
      power *= 2
23
  return bits
24
 
25
def to_gray(i):
26
 
27
  """Convert integer to gray code"""
28
 
29
  return (i >> 1) ^ i
30
 
31
def generate_CHIP(input_file,
32
                  name,
33
                  frames,
34
                  output_file,
35
                  registers,
36
                  memory_size_2,
37
                  memory_size_4,
38
                  initialize_memory,
39
                  memory_content_2,
40
                  memory_content_4,
41
                  no_tb_mode=False):
42
 
43
  """A big ugly function to crunch through all the instructions and generate the CHIP equivilent"""
44
 
45
  #calculate the values of jump locations
46
  location = 0
47
  labels = {}
48
  new_frames = []
49
  for frame in frames:
50
    if frame[0]["op"] == "label":
51
      labels[frame[0]["label"]] = location
52
    else:
53
      new_frames.append(frame)
54
      location += 1
55
  frames = new_frames
56
 
57
  #substitue real values for labeled jump locations
58
  for frame in frames:
59
    for instruction in frame:
60
      if "label" in instruction:
61
        instruction["label"]=labels[instruction["label"]]
62
 
63
  #list all inputs and outputs used in the program
64
  inputs = unique([i["input"] for frame in frames for i in frame if "input" in i])
65
  outputs = unique([i["output"] for frame in frames for i in frame if "output" in i])
66
  input_files = unique([i["file_name"] for frame in frames for i in frame if "file_read" == i["op"]])
67
  output_files = unique([i["file_name"] for frame in frames for i in frame if "file_write" == i["op"]])
68
  testbench = not inputs and not outputs and not no_tb_mode
69
 
70
  #Do not generate a port in testbench mode
71
  inports = [
72
    ("input_" + i, 16) for i in inputs
73
  ] + [
74
    ("input_" + i + "_stb", 1) for i in inputs
75
  ] + [
76
    ("output_" + i + "_ack", 1) for i in outputs
77
  ]
78
 
79
  outports = [
80
    ("output_" + i, 16) for i in outputs
81
  ] + [
82
    ("output_" + i + "_stb", 1) for i in outputs
83
  ] + [
84
    ("input_" + i + "_ack", 1) for i in inputs
85
  ]
86
 
87
  #create list of signals
88
  signals = [
89
    ("timer", 16),
90
    ("program_counter", log2(len(frames))),
91
    ("address_2", 16),
92
    ("data_out_2", 16),
93
    ("data_in_2", 16),
94
    ("write_enable_2", 1),
95
    ("address_4", 16),
96
    ("data_out_4", 32),
97
    ("data_in_4", 32),
98
    ("write_enable_4", 1),
99
  ] + [
100
    ("register_%s"%(register), definition[1]*8) for register, definition in registers.iteritems()
101
  ] + [
102
    ("s_output_" + i + "_stb", 16) for i in outputs
103
  ] + [
104
    ("s_output_" + i, 16) for i in outputs
105
  ] + [
106
    ("s_input_" + i + "_ack", 16) for i in inputs
107
  ]
108
 
109
  if testbench:
110
    signals.append(("clk", 1))
111
    signals.append(("rst", 1))
112
  else:
113
    inports.append(("clk", 1))
114
    inports.append(("rst", 1))
115
 
116
  #output the code in verilog
117
  output_file.write("//name : %s\n"%name)
118
  output_file.write("//tag : c components\n")
119
  for i in inputs:
120
      output_file.write("//input : input_%s:16\n"%i)
121
  for i in outputs:
122
      output_file.write("//output : output_%s:16\n"%i)
123
  output_file.write("//source_file : %s\n"%input_file)
124
  output_file.write("///%s\n"%"".join(["=" for i in name]))
125
  output_file.write("///\n")
126
  output_file.write("///*Created by C2CHIP*\n\n")
127
 
128
 
129
  output_file.write("// Register Allocation\n")
130
  output_file.write("// ===================\n")
131
  output_file.write("//   %s   %s   %s  \n"%("Register".center(20), "Name".center(20), "Size".center(20)))
132
  for register, definition in registers.iteritems():
133
      register_name, size = definition
134
      output_file.write("//   %s   %s   %s  \n"%(str(register).center(20), register_name.center(20), str(size).center(20)))
135
 
136
  output_file.write("  \n`timescale 1ns/1ps\n")
137
  output_file.write("module %s"%name)
138
 
139
  all_ports = [name for name, size in inports + outports]
140
  if all_ports:
141
      output_file.write("(")
142
      output_file.write(",".join(all_ports))
143
      output_file.write(");\n")
144
  else:
145
      output_file.write(";\n")
146
 
147
  output_file.write("  integer file_count;\n")
148
 
149
  input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)]))
150
  for i in input_files.values():
151
      output_file.write("  integer %s;\n"%i)
152
 
153
  output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)]))
154
  for i in output_files.values():
155
      output_file.write("  integer %s;\n"%i)
156
 
157
 
158
  def write_declaration(object_type, name, size, value=None):
159
      if size == 1:
160
          output_file.write(object_type)
161
          output_file.write(name)
162
          if value is not None:
163
              output_file.write("= %s'd%s"%(size,value))
164
          output_file.write(";\n")
165
      else:
166
          output_file.write(object_type)
167
          output_file.write("[%i:0]"%(size-1))
168
          output_file.write(" ")
169
          output_file.write(name)
170
          if value is not None:
171
              output_file.write("= %s'd%s"%(size,value))
172
          output_file.write(";\n")
173
 
174
  for name, size in inports:
175
      write_declaration("  input     ", name, size)
176
 
177
  for name, size in outports:
178
      write_declaration("  output    ", name, size)
179
 
180
  for name, size in signals:
181
      write_declaration("  reg       ", name, size)
182
 
183
  memory_size_2 = int(memory_size_2)
184
  memory_size_4 = int(memory_size_4)
185
  if memory_size_2:
186
      output_file.write("  reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1))
187
  if memory_size_4:
188
      output_file.write("  reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1))
189
 
190
  #generate clock and reset in testbench mode
191
  if testbench:
192
 
193
      output_file.write("\n  //////////////////////////////////////////////////////////////////////////////\n")
194
      output_file.write("  // CLOCK AND RESET GENERATION                                                 \n")
195
      output_file.write("  //                                                                            \n")
196
      output_file.write("  // This file was generated in test bench mode. In this mode, the verilog      \n")
197
      output_file.write("  // output file can be executed directly within a verilog simulator.           \n")
198
      output_file.write("  // In test bench mode, a simulated clock and reset signal are generated within\n")
199
      output_file.write("  // the output file.                                                           \n")
200
      output_file.write("  // Verilog files generated in testbecnch mode are not suitable for synthesis, \n")
201
      output_file.write("  // or for instantiation within a larger design.\n")
202
 
203
      output_file.write("  \n  initial\n")
204
      output_file.write("  begin\n")
205
      output_file.write("    rst <= 1'b1;\n")
206
      output_file.write("    #50 rst <= 1'b0;\n")
207
      output_file.write("  end\n\n")
208
 
209
      output_file.write("  \n  initial\n")
210
      output_file.write("  begin\n")
211
      output_file.write("    clk <= 1'b0;\n")
212
      output_file.write("    while (1) begin\n")
213
      output_file.write("      #5 clk <= ~clk;\n")
214
      output_file.write("    end\n")
215
      output_file.write("  end\n\n")
216
 
217
  #Generate a state machine to execute the instructions
218
  binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=",
219
    "<=", "==", "!="]
220
 
221
 
222
  if initialize_memory and (memory_content_2 or memory_content_4):
223
 
224
      output_file.write("\n  //////////////////////////////////////////////////////////////////////////////\n")
225
      output_file.write("  // MEMORY INITIALIZATION                                                      \n")
226
      output_file.write("  //                                                                            \n")
227
      output_file.write("  // In order to reduce program size, array contents have been stored into      \n")
228
      output_file.write("  // memory at initialization. In an FPGA, this will result in the memory being \n")
229
      output_file.write("  // initialized when the FPGA configures.                                      \n")
230
      output_file.write("  // Memory will not be re-initialized at reset.                                \n")
231
      output_file.write("  // Dissable this behaviour using the no_initialize_memory switch              \n")
232
 
233
      output_file.write("  \n  initial\n")
234
      output_file.write("  begin\n")
235
      for location, content in memory_content_2.iteritems():
236
          output_file.write("    memory_2[%s] = %s;\n"%(location, content))
237
      for location, content in memory_content_4.iteritems():
238
          output_file.write("    memory_4[%s] = %s;\n"%(location, content))
239
      output_file.write("  end\n\n")
240
 
241
  if input_files or output_files:
242
 
243
      output_file.write("\n  //////////////////////////////////////////////////////////////////////////////\n")
244
      output_file.write("  // OPEN FILES                                                                 \n")
245
      output_file.write("  //                                                                            \n")
246
      output_file.write("  // Open all files used at the start of the process                            \n")
247
 
248
      output_file.write("  \n  initial\n")
249
      output_file.write("  begin\n")
250
      for file_name, file_ in input_files.iteritems():
251
          output_file.write("    %s = $fopenr(\"%s\");\n"%(file_, file_name))
252
      for file_name, file_ in output_files.iteritems():
253
          output_file.write("    %s = $fopen(\"%s\");\n"%(file_, file_name))
254
      output_file.write("  end\n\n")
255
 
256
  output_file.write("\n  //////////////////////////////////////////////////////////////////////////////\n")
257
  output_file.write("  // FSM IMPLEMENTAION OF C PROCESS                                             \n")
258
  output_file.write("  //                                                                            \n")
259
  output_file.write("  // This section of the file contains a Finite State Machine (FSM) implementing\n")
260
  output_file.write("  // the C process. In general execution is sequential, but the compiler will   \n")
261
  output_file.write("  // attempt to execute instructions in parallel if the instruction dependencies\n")
262
  output_file.write("  // allow. Further concurrency can be achieved by executing multiple C         \n")
263
  output_file.write("  // processes concurrently within the device.                                  \n")
264
 
265
  output_file.write("  \n  always @(posedge clk)\n")
266
  output_file.write("  begin\n\n")
267
 
268
  if memory_size_2:
269
      output_file.write("    //implement memory for 2 byte x n arrays\n")
270
      output_file.write("    if (write_enable_2 == 1'b1) begin\n")
271
      output_file.write("      memory_2[address_2] <= data_in_2;\n")
272
      output_file.write("    end\n")
273
      output_file.write("    data_out_2 <= memory_2[address_2];\n")
274
      output_file.write("    write_enable_2 <= 1'b0;\n\n")
275
 
276
  if memory_size_4:
277
      output_file.write("    //implement memory for 4 byte x n arrays\n")
278
      output_file.write("    if (write_enable_4 == 1'b1) begin\n")
279
      output_file.write("      memory_4[address_4] <= data_in_4;\n")
280
      output_file.write("    end\n")
281
      output_file.write("    data_out_4 <= memory_4[address_4];\n")
282
      output_file.write("    write_enable_4 <= 1'b0;\n\n")
283
 
284
  output_file.write("    //implement timer\n")
285
  output_file.write("    timer <= 16'h0000;\n\n")
286
  output_file.write("    case(program_counter)\n\n")
287
 
288
  #A frame is executed in each state
289
  for location, frame in enumerate(frames):
290
    output_file.write("      16'd%s:\n"%to_gray(location))
291
    output_file.write("      begin\n")
292
    output_file.write("        program_counter <= 16'd%s;\n"%to_gray(location+1))
293
    for instruction in frame:
294
 
295
      if instruction["op"] == "literal":
296
        output_file.write(
297
          "        register_%s <= %s;\n"%(
298
          instruction["dest"],
299
          instruction["literal"]))
300
 
301
      elif instruction["op"] == "move":
302
        output_file.write(
303
          "        register_%s <= register_%s;\n"%(
304
          instruction["dest"],
305
          instruction["src"]))
306
 
307
      elif instruction["op"] in ["~"]:
308
        output_file.write(
309
          "        register_%s <= ~register_%s;\n"%(
310
          instruction["dest"],
311
          instruction["src"]))
312
 
313
      elif instruction["op"] in binary_operators and "left" in instruction:
314
        if not instruction["signed"]:
315
            output_file.write(
316
              "        register_%s <= %s %s $unsigned(register_%s);\n"%(
317
              instruction["dest"],
318
              instruction["left"],
319
              instruction["op"],
320
              instruction["src"]))
321
        else:
322
            #Verilog uses >>> as an arithmetic right shift
323
            if instruction["op"] == ">>":
324
                instruction["op"] = ">>>"
325
            output_file.write(
326
              "        register_%s <= %s %s $signed(register_%s);\n"%(
327
              instruction["dest"],
328
              instruction["left"],
329
              instruction["op"],
330
              instruction["src"]))
331
 
332
      elif instruction["op"] in binary_operators and "right" in instruction:
333
        if not instruction["signed"]:
334
            output_file.write(
335
              "        register_%s <= $unsigned(register_%s) %s %s;\n"%(
336
              instruction["dest"],
337
              instruction["src"],
338
              instruction["op"],
339
              instruction["right"]))
340
        else:
341
            #Verilog uses >>> as an arithmetic right shift
342
            if instruction["op"] == ">>":
343
                instruction["op"] = ">>>"
344
            output_file.write(
345
              "        register_%s <= $signed(register_%s) %s %s;\n"%(
346
              instruction["dest"],
347
              instruction["src"],
348
              instruction["op"],
349
              instruction["right"]))
350
 
351
      elif instruction["op"] in binary_operators:
352
        if not instruction["signed"]:
353
            output_file.write(
354
              "        register_%s <= $unsigned(register_%s) %s $unsigned(register_%s);\n"%(
355
              instruction["dest"],
356
              instruction["src"],
357
              instruction["op"],
358
              instruction["srcb"]))
359
        else:
360
            #Verilog uses >>> as an arithmetic right shift
361
            if instruction["op"] == ">>":
362
                instruction["op"] = ">>>"
363
            output_file.write(
364
              "        register_%s <= $signed(register_%s) %s $signed(register_%s);\n"%(
365
              instruction["dest"],
366
              instruction["src"],
367
              instruction["op"],
368
              instruction["srcb"]))
369
 
370
      elif instruction["op"] == "jmp_if_false":
371
        output_file.write("        if (register_%s == 0)\n"%(instruction["src"]));
372
        output_file.write("          program_counter <= %s;\n"%to_gray(instruction["label"]&0xffff))
373
 
374
      elif instruction["op"] == "jmp_if_true":
375
        output_file.write("        if (register_%s != 0)\n"%(instruction["src"]));
376
        output_file.write("          program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff))
377
 
378
      elif instruction["op"] == "jmp_and_link":
379
        output_file.write("        program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff))
380
        output_file.write("        register_%s <= 16'd%s;\n"%(
381
          instruction["dest"], to_gray((location+1)&0xffff)))
382
 
383
      elif instruction["op"] == "jmp_to_reg":
384
        output_file.write(
385
          "        program_counter <= register_%s;\n"%instruction["src"])
386
 
387
      elif instruction["op"] == "goto":
388
        output_file.write("        program_counter <= 16'd%s;\n"%(to_gray(instruction["label"]&0xffff)))
389
 
390
      elif instruction["op"] == "file_read":
391
        output_file.write("        file_count = $fscanf(%s, \"%%d\\n\", register_%s);\n"%(
392
          input_files[instruction["file_name"]], instruction["dest"]))
393
 
394
      elif instruction["op"] == "file_write":
395
        output_file.write("        $fdisplay(%s, \"%%d\", register_%s);\n"%(
396
          output_files[instruction["file_name"]], instruction["src"]))
397
 
398
      elif instruction["op"] == "read":
399
        output_file.write("        register_%s <= input_%s;\n"%(
400
          instruction["dest"], instruction["input"]))
401
        output_file.write("        program_counter <= %s;\n"%to_gray(location))
402
        output_file.write("        s_input_%s_ack <= 1'b1;\n"%instruction["input"])
403
        output_file.write( "       if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%(
404
          instruction["input"],
405
          instruction["input"]
406
        ))
407
        output_file.write("          s_input_%s_ack <= 1'b0;\n"%instruction["input"])
408
        output_file.write("          program_counter <= 16'd%s;\n"%to_gray(location+1))
409
        output_file.write("        end\n")
410
 
411
      elif instruction["op"] == "ready":
412
        output_file.write("        register_%s <= 0;\n"%instruction["dest"])
413
        output_file.write("        register_%s[0] <= input_%s_stb;\n"%(
414
          instruction["dest"], instruction["input"]))
415
 
416
      elif instruction["op"] == "write":
417
        output_file.write("        s_output_%s <= register_%s;\n"%(
418
          instruction["output"], instruction["src"]))
419
        output_file.write("        program_counter <= %s;\n"%to_gray(location))
420
        output_file.write("        s_output_%s_stb <= 1'b1;\n"%instruction["output"])
421
        output_file.write(
422
          "        if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%(
423
          instruction["output"],
424
          instruction["output"]
425
        ))
426
        output_file.write("          s_output_%s_stb <= 1'b0;\n"%instruction["output"])
427
        output_file.write("          program_counter <= %s;\n"%to_gray(location+1))
428
        output_file.write("        end\n")
429
 
430
      elif instruction["op"] == "memory_read_request":
431
        output_file.write(
432
          "        address_%s <= register_%s;\n"%(
433
              instruction["element_size"],
434
              instruction["src"])
435
        )
436
 
437
      elif instruction["op"] == "memory_read_wait":
438
        pass
439
 
440
      elif instruction["op"] == "memory_read":
441
        output_file.write(
442
          "        register_%s <= data_out_%s;\n"%(
443
              instruction["dest"],
444
              instruction["element_size"])
445
        )
446
 
447
      elif instruction["op"] == "memory_write":
448
        output_file.write("        address_%s <= register_%s;\n"%(
449
            instruction["element_size"],
450
            instruction["src"])
451
        )
452
        output_file.write("        data_in_%s <= register_%s;\n"%(
453
            instruction["element_size"],
454
            instruction["srcb"])
455
        )
456
        output_file.write("        write_enable_%s <= 1'b1;\n"%(
457
            instruction["element_size"])
458
        )
459
 
460
      elif instruction["op"] == "memory_write_literal":
461
        output_file.write("        address_%s <= 16'd%s;\n"%(
462
            instruction["element_size"],
463
            instruction["address"])
464
        )
465
        output_file.write("        data_in_%s <= %s;\n"%(
466
            instruction["element_size"],
467
            instruction["value"])
468
        )
469
        output_file.write("        write_enable_%s <= 1'b1;\n"%(
470
            instruction["element_size"])
471
        )
472
 
473
      elif instruction["op"] == "assert":
474
        output_file.write( "        if (register_%s == 0) begin\n"%instruction["src"])
475
        output_file.write( "          $display(\"Assertion failed at line: %s in file: %s\");\n"%(
476
          instruction["line"],
477
          instruction["file"]
478
        ))
479
        output_file.write( "          $finish_and_return(1);\n")
480
        output_file.write( "        end\n")
481
 
482
      elif instruction["op"] == "wait_clocks":
483
        output_file.write("        if (timer < register_%s) begin\n"%instruction["src"])
484
        output_file.write("          program_counter <= program_counter;\n")
485
        output_file.write("          timer <= timer+1;\n")
486
        output_file.write("        end\n")
487
 
488
      elif instruction["op"] == "report":
489
        if not instruction["signed"]:
490
            output_file.write(
491
              '        $display ("%%d (report at line: %s in file: %s)", $unsigned(register_%s));\n'%(
492
              instruction["line"],
493
              instruction["file"],
494
              instruction["src"],
495
            ))
496
        else:
497
            output_file.write(
498
              '        $display ("%%d (report at line: %s in file: %s)", $signed(register_%s));\n'%(
499
              instruction["line"],
500
              instruction["file"],
501
              instruction["src"],
502
            ))
503
 
504
      elif instruction["op"] == "stop":
505
        #If we are in testbench mode stop the simulation
506
        #If we are part of a larger design, other C programs may still be running
507
        for file_ in input_files.values():
508
            output_file.write("        $fclose(%s);\n"%file_)
509
        for file_ in output_files.values():
510
            output_file.write("        $fclose(%s);\n"%file_)
511
        if testbench:
512
            output_file.write('        $finish;\n')
513
        output_file.write("        program_counter <= program_counter;\n")
514
    output_file.write("      end\n\n")
515
 
516
  output_file.write("    endcase\n")
517
 
518
  #Reset program counter and control signals
519
  output_file.write("    if (rst == 1'b1) begin\n")
520
  output_file.write("      program_counter <= 0;\n")
521
  for i in inputs:
522
      output_file.write("      s_input_%s_ack <= 0;\n"%(i))
523
  for i in outputs:
524
      output_file.write("      s_output_%s_stb <= 0;\n"%(i))
525
  output_file.write("    end\n")
526
  output_file.write("  end\n")
527
  for i in inputs:
528
    output_file.write("  assign input_%s_ack = s_input_%s_ack;\n"%(i, i))
529
  for i in outputs:
530
    output_file.write("  assign output_%s_stb = s_output_%s_stb;\n"%(i, i))
531
    output_file.write("  assign output_%s = s_output_%s;\n"%(i, i))
532
  output_file.write("\nendmodule\n")
533
 
534
  return inputs, outputs

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.