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 4

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 4 jondawson
    them which chip they belong to. Once you have a completed chip you can:
11 2 jondawson
 
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 4 jondawson
            return os.system("vvp %s"%(self.name + "_tb"))
159 2 jondawson
 
160
 
161
class Component:
162
 
163
    """You can use the component class to add new components to your chip.
164
    Components are written in C, and you need to supply the C code for the
165
    component when you create it. The Chips API will automatically compile the
166
    C code, and extract the name, inputs, outputs and the documentation from the
167
    code.
168 4 jondawson
 
169 2 jondawson
    If you want to keep the C file seperate you can read it in from a file like
170
    this::
171
 
172
        my_component = Adder(C_file="adder.c")
173
 
174
    Once you have defined a component you can use the __call__ method to create
175
    an instance of the component.
176 4 jondawson
 
177 2 jondawson
    """
178
 
179
    def __init__(self, C_file):
180
 
181
        """Takes a single string argument, the C code to compile"""
182
 
183
        self.name, self.inputs, self.outputs, self.doc = chips.compiler.compiler.comp(C_file)
184
 
185
    def __call__(self, chip, inputs, outputs):
186
 
187
        """Takes three arguments:
188
            + chip, the chip that the component instance belongs to.
189
            + inputs, a list of *Wires* (or *Inputs*) to connect to the component inputs
190
            + outputs, a list of *Wires* (or *Outputs*) to connect to the component outputs"""
191
        return _Instance(self, chip, inputs, outputs)
192
 
193
 
194 4 jondawson
class VerilogComponent(Component):
195
 
196
    """You can use the component class to add new components to your chip.
197
    This version of Component allows components to be written directly in verilog.
198
 
199
        my_component = Adder("adder", inputs = ["a", "b"], outputs = ["z"])
200
 
201
    Once you have defined a component you can use the __call__ method to create
202
    an instance of the component.
203
 
204
    """
205
 
206
    def __init__(self, name, inputs, outputs, docs):
207
 
208
        """Takes a single string argument, the C code to compile"""
209
 
210
        self.name = name
211
        self.inputs = inputs
212
        self.outputs = outputs
213
        self.docs = docs
214
 
215
 
216 2 jondawson
class _Instance:
217
 
218
    """This class represents a component instance. You don't normaly need to
219
    create them directly, use the Component.__call__ method."""
220 4 jondawson
 
221 2 jondawson
    def __init__(self, component, chip, inputs, outputs):
222
        self.chip = chip
223
        self.inputs = inputs
224
        self.outputs = outputs
225
        self.component = component
226
        self.chip.instances.append(self)
227
        if component not in chip.components:
228
            chip.components.append(component)
229
 
230
        if len(self.component.inputs) != len(self.inputs):
231
            raise C2CHIPError("Instance %s does not have the right number or inputs"%self.name)
232
 
233
        if len(self.component.outputs) != len(self.outputs):
234
            raise C2CHIPError("Instance %s does not have the right number or outputs"%self.name)
235
 
236
        for i in inputs.values():
237
            if i.sink is not None:
238
                raise C2CHIPError("%s allready has a sink"%i.name)
239
            i.sink = self
240
 
241
        for i in outputs.values():
242
            if i.source is not None:
243
                raise C2CHIPError("%s has allready has a source"%i.name)
244
            i.source = self
245
 
246
        for i in inputs.keys():
247
            if i not in self.component.inputs:
248
                raise C2CHIPError("%s is not an input of component %s"%(i, component.name))
249
 
250
        for i in outputs.keys():
251
            if i not in self.component.outputs:
252
                raise C2CHIPError("%s has allready has a source %s"%(i, component.name))
253
 
254
class Wire:
255
 
256
    """Create a connection between two components. A wire is a point to point
257
    connection with one input and one output"""
258
 
259
    def __init__(self, chip):
260
        self.chip = chip
261
        chip.wires.append(self)
262
        self.source = None
263
        self.sink = None
264
        self.name = "wire_" + str(id(self))
265
 
266
class Input:
267
 
268
    """Create an input to the chip."""
269
 
270
    def __init__(self, chip, name):
271
 
272
        """Takes a single argument, the chip to which the input belongs, and a
273
        string representing the name"""
274
 
275
        self.chip = chip
276
        chip.inputs.append(self)
277
        self.sink = None
278
        self.name = name
279
 
280
class Output:
281
 
282
    """Create an output from the chip."""
283
 
284
    def __init__(self, chip, name):
285
 
286
        """Takes two argument, the chip to which the output belongs, and a
287
        string representing the name"""
288
 
289
        self.chip = chip
290
        chip.outputs.append(self)
291
        self.source = None
292
        self.name = name

powered by: WebSVN 2.1.0

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