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

Subversion Repositories tcp_socket

[/] [tcp_socket/] [trunk/] [chips2/] [chips/] [api/] [api.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
from chips.compiler.exceptions import C2CHIPError
2
import chips.compiler.compiler
3
import os
4
import sys
5
 
6
class Chip:
7
 
8
    """A Chip represents a collection of components connected together by
9
    wires. As you create wires and component instances, you will need to tell
10
    them which chip they belong to. Once you have a completed chip you can:
11
 
12
      + Implement it in verilog - using the generate_verilog method
13
      + Automatically generate documentation - using the generate_document method
14
 
15
    You can create a new chip like this::
16
 
17
        my_chip = Chip(name = "My Chip")"""
18
 
19
 
20
    def __init__(self, name):
21
 
22
        """Takes a single argument *name*, the name of the chip"""
23
 
24
        self.name = name
25
        self.instances = []
26
        self.wires = []
27
        self.inputs = []
28
        self.outputs = []
29
        self.components = []
30
 
31
    def generate_verilog(self):
32
 
33
        """Generate verilog for the chip"""
34
 
35
        for i in self.wires:
36
            if i.source is None:
37
                raise C2CHIPError("wire %s has no source"%i.name)
38
            if i.sink is None:
39
                raise C2CHIPError("wire %s has no sink"%i.name)
40
 
41
        for i in self.inputs:
42
            if i.sink is None:
43
                raise C2CHIPError("input %s has no sink"%i.name)
44
 
45
        for i in self.outputs:
46
            if i.source is None:
47
                raise C2CHIPError("output %s has no source"%i.name)
48
 
49
        ports = ["clk", "rst"]
50
        ports += ["%s"%i.name for i in self.inputs]
51
        ports += ["%s_stb"%i.name for i in self.inputs]
52
        ports += ["%s_ack"%i.name for i in self.inputs]
53
        ports += ["%s"%i.name for i in self.outputs]
54
        ports += ["%s_stb"%i.name for i in self.outputs]
55
        ports += ["%s_ack"%i.name for i in self.outputs]
56
        ports = ", ".join(ports)
57
 
58
        output_file = open(self.name + ".v", "w")
59
        output_file.write("module %s(%s);\n"%(self.name, ports))
60
        output_file.write("  input  clk;\n")
61
        output_file.write("  input  rst;\n")
62
        for i in self.inputs:
63
            output_file.write("  input  [15:0] %s;\n"%i.name)
64
            output_file.write("  input  %s_stb;\n"%i.name)
65
            output_file.write("  output %s_ack;\n"%i.name)
66
        for i in self.outputs:
67
            output_file.write("  output [15:0] %s;\n"%i.name)
68
            output_file.write("  output %s_stb;\n"%i.name)
69
            output_file.write("  input  %s_ack;\n"%i.name)
70
        for i in self.wires:
71
            output_file.write("  wire   [15:0] %s;\n"%i.name)
72
            output_file.write("  wire   %s_stb;\n"%i.name)
73
            output_file.write("  wire   %s_ack;\n"%i.name)
74
        for instance in self.instances:
75
            component = instance.component.name
76
            output_file.write("  %s %s_%s(\n    "%(component, component, id(instance)))
77
            ports = []
78
            ports.append(".clk(clk)")
79
            ports.append(".rst(rst)")
80
            for name, i in instance.inputs.iteritems():
81
                ports.append(".input_%s(%s)"%(name, i.name))
82
                ports.append(".input_%s_stb(%s_stb)"%(name, i.name))
83
                ports.append(".input_%s_ack(%s_ack)"%(name, i.name))
84
            for name, i in instance.outputs.iteritems():
85
                ports.append(".output_%s(%s)"%(name, i.name))
86
                ports.append(".output_%s_stb(%s_stb)"%(name, i.name))
87
                ports.append(".output_%s_ack(%s_ack)"%(name, i.name))
88
            output_file.write(",\n    ".join(ports))
89
            output_file.write(");\n")
90
        output_file.write("endmodule\n")
91
        output_file.close()
92
 
93
    def generate_testbench(self, stop_clocks=None):
94
 
95
        """Generate verilog for the test bench"""
96
 
97
        output_file = open(self.name + "_tb.v", "w")
98
        output_file.write("module %s_tb;\n"%self.name)
99
        output_file.write("  reg  clk;\n")
100
        output_file.write("  reg  rst;\n")
101
        for i in self.inputs:
102
            output_file.write("  wire  [15:0] %s;\n"%i.name)
103
            output_file.write("  wire  [15:0] %s_stb;\n"%i.name)
104
            output_file.write("  wire  [15:0] %s_ack;\n"%i.name)
105
        for i in self.outputs:
106
            output_file.write("  wire  [15:0] %s;\n"%i.name)
107
            output_file.write("  wire  [15:0] %s_stb;\n"%i.name)
108
            output_file.write("  wire  [15:0] %s_ack;\n"%i.name)
109
 
110
        output_file.write("  \n  initial\n")
111
        output_file.write("  begin\n")
112
        output_file.write("    rst <= 1'b1;\n")
113
        output_file.write("    #50 rst <= 1'b0;\n")
114
        output_file.write("  end\n\n")
115
 
116
        if stop_clocks:
117
            output_file.write("  \n  initial\n")
118
            output_file.write("  begin\n")
119
            output_file.write("    #%s $finish;\n"%(10*stop_clocks))
120
            output_file.write("  end\n\n")
121
 
122
        output_file.write("  \n  initial\n")
123
        output_file.write("  begin\n")
124
        output_file.write("    clk <= 1'b0;\n")
125
        output_file.write("    while (1) begin\n")
126
        output_file.write("      #5 clk <= ~clk;\n")
127
        output_file.write("    end\n")
128
        output_file.write("  end\n\n")
129
 
130
        output_file.write("  %s uut(\n    "%(self.name))
131
        ports = []
132
        ports.append(".clk(clk)")
133
        ports.append(".rst(rst)")
134
        for i in self.inputs:
135
            ports.append(".%s(%s)"%(i.name, i.name))
136
            ports.append(".%s_stb(%s_stb)"%(i.name, i.name))
137
            ports.append(".%s_ack(%s_ack)"%(i.name, i.name))
138
        for i in self.outputs:
139
            ports.append(".%s(%s)"%(i.name, i.name))
140
            ports.append(".%s_stb(%s_stb)"%(i.name, i.name))
141
            ports.append(".%s_ack(%s_ack)"%(i.name, i.name))
142
        output_file.write(",\n    ".join(ports))
143
        output_file.write(");\n")
144
        output_file.write("endmodule\n")
145
        output_file.close()
146
 
147
    def compile_iverilog(self, run=False):
148
 
149
        """Compile using the Iverilog simulator"""
150
 
151
        files = ["%s.v"%i.name for i in self.components]
152
        files.append(self.name + ".v")
153
        files.append(self.name + "_tb.v")
154
        files = " ".join(files)
155
 
156
        os.system("iverilog -o %s %s"%(self.name + "_tb", files))
157
        if run:
158
          return os.system("vvp %s"%(self.name + "_tb"))
159
 
160
 
161
 
162
class Component:
163
 
164
    """You can use the component class to add new components to your chip.
165
    Components are written in C, and you need to supply the C code for the
166
    component when you create it. The Chips API will automatically compile the
167
    C code, and extract the name, inputs, outputs and the documentation from the
168
    code.
169
 
170
    If you want to keep the C file seperate you can read it in from a file like
171
    this::
172
 
173
        my_component = Adder(C_file="adder.c")
174
 
175
    Once you have defined a component you can use the __call__ method to create
176
    an instance of the component.
177
 
178
    """
179
 
180
    def __init__(self, C_file):
181
 
182
        """Takes a single string argument, the C code to compile"""
183
 
184
        self.name, self.inputs, self.outputs, self.doc = chips.compiler.compiler.comp(C_file)
185
 
186
    def __call__(self, chip, inputs, outputs):
187
 
188
        """Takes three arguments:
189
            + chip, the chip that the component instance belongs to.
190
            + inputs, a list of *Wires* (or *Inputs*) to connect to the component inputs
191
            + outputs, a list of *Wires* (or *Outputs*) to connect to the component outputs"""
192
        return _Instance(self, chip, inputs, outputs)
193
 
194
 
195
class _Instance:
196
 
197
    """This class represents a component instance. You don't normaly need to
198
    create them directly, use the Component.__call__ method."""
199
 
200
    def __init__(self, component, chip, inputs, outputs):
201
        self.chip = chip
202
        self.inputs = inputs
203
        self.outputs = outputs
204
        self.component = component
205
        self.chip.instances.append(self)
206
        if component not in chip.components:
207
            chip.components.append(component)
208
 
209
        if len(self.component.inputs) != len(self.inputs):
210
            raise C2CHIPError("Instance %s does not have the right number or inputs"%self.name)
211
 
212
        if len(self.component.outputs) != len(self.outputs):
213
            raise C2CHIPError("Instance %s does not have the right number or outputs"%self.name)
214
 
215
        for i in inputs.values():
216
            if i.sink is not None:
217
                raise C2CHIPError("%s allready has a sink"%i.name)
218
            i.sink = self
219
 
220
        for i in outputs.values():
221
            if i.source is not None:
222
                raise C2CHIPError("%s has allready has a source"%i.name)
223
            i.source = self
224
 
225
        for i in inputs.keys():
226
            if i not in self.component.inputs:
227
                raise C2CHIPError("%s is not an input of component %s"%(i, component.name))
228
 
229
        for i in outputs.keys():
230
            if i not in self.component.outputs:
231
                raise C2CHIPError("%s has allready has a source %s"%(i, component.name))
232
 
233
class Wire:
234
 
235
    """Create a connection between two components. A wire is a point to point
236
    connection with one input and one output"""
237
 
238
    def __init__(self, chip):
239
        self.chip = chip
240
        chip.wires.append(self)
241
        self.source = None
242
        self.sink = None
243
        self.name = "wire_" + str(id(self))
244
 
245
class Input:
246
 
247
    """Create an input to the chip."""
248
 
249
    def __init__(self, chip, name):
250
 
251
        """Takes a single argument, the chip to which the input belongs, and a
252
        string representing the name"""
253
 
254
        self.chip = chip
255
        chip.inputs.append(self)
256
        self.sink = None
257
        self.name = name
258
 
259
class Output:
260
 
261
    """Create an output from the chip."""
262
 
263
    def __init__(self, chip, name):
264
 
265
        """Takes two argument, the chip to which the output belongs, and a
266
        string representing the name"""
267
 
268
        self.chip = chip
269
        chip.outputs.append(self)
270
        self.source = None
271
        self.name = name

powered by: WebSVN 2.1.0

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