def __init__(self, component, chip, inputs, outputs): self.chip = chip self.inputs = inputs self.outputs = outputs self.component = component self.chip.instances.append(self) if component not in chip.components: chip.components.append(component) if len(self.component.inputs) != len(self.inputs): raise C2CHIPError("Instance %s does not have the right number or inputs"%self.name) if len(self.component.outputs) != len(self.outputs): raise C2CHIPError("Instance %s does not have the right number or outputs"%self.name) for i in inputs.values(): if i.sink is not None: raise C2CHIPError("%s allready has a sink"%i.name) i.sink = self for i in outputs.values(): if i.source is not None: raise C2CHIPError("%s has allready has a source"%i.name) i.source = self for i in inputs.keys(): if i not in self.component.inputs: raise C2CHIPError("%s is not an input of component %s"%(i, component.name)) for i in outputs.keys(): if i not in self.component.outputs: raise C2CHIPError("%s has allready has a source %s"%(i, component.name))
def prepare_for_simulation(self, inputs, outputs): # for io_port in self.inputs.values() + self.outputs.values(): # io_port.delete() self.inputs = inputs self.outputs = outputs # generate a python simulation model of the instance ret = chips.compiler.compiler.make_python_model( self.asm_program, inputs, outputs, self.debug, self.profile) #TODO use inputs/outputs from asm_program self.model, component_inputs, component_outputs = ret # check that correct number of wires have been passed in if len(component_inputs) != len(self.inputs): for i in component_inputs: print "component inputs:" for i in self.inputs: print "instance inputs:" raise C2CHIPError( "Instance %s does not have the right number or inputs" % (self.component_name)) if len(component_outputs) != len(self.outputs): raise C2CHIPError( "Instance %s does not have the right number or outputs" % (self.component_name)) # check for multiple sources or sinks for i in inputs.values(): if i.sink is not None: raise C2CHIPError("%s already has a sink" % i.name, i.filename, i.lineno) i.sink = self for i in outputs.values(): if i.source is not None: raise C2CHIPError("%s has already has a source" % (i.name, i.filename, i.lineno)) i.source = self for i in inputs.keys(): if i not in component_inputs: raise C2CHIPError( "%s is not an input of component %s" % (i, self.component_name), i.filename, i.lineno) for i in outputs.keys(): if i not in component_outputs: raise C2CHIPError( "%s is not an output of component %s" % (i, self.component_name), i.filename, i.lineno)
def __init__(self, component, chip, parameters, inputs, outputs, debug=False, profile=False): self.chip = chip self.parameters = parameters self.inputs = inputs self.outputs = outputs self.component = component self.chip.instances.append(self) self.debug = debug self.profile = profile self.sn = chip.sn chip.sn += 1 _, self.filename, self.lineno, _, _, _ = inspect.stack()[1] # generate a python simulation model of the instance ret = chips.compiler.compiler.compile_python_model( self.component.C_file, self.component.options, parameters, inputs, outputs, self.debug, self.profile, self.sn) self.model, component_inputs, component_outputs, component_name = ret self.component_name = component_name if component_name not in chip.components: chip.components[component_name] = self # check that correct number of wires have been passed in if len(component_inputs) != len(self.inputs): for i in component_inputs: print "component inputs:" for i in self.inputs: print "instance inputs:" raise C2CHIPError( "Instance %s does not have the right number or inputs" % (component_name)) if len(component_outputs) != len(self.outputs): raise C2CHIPError( "Instance %s does not have the right number or outputs" % (component_name)) # check for multiple sources or sinks for i in inputs.values(): if i.sink is not None: raise C2CHIPError("%s already has a sink" % i.name, i.filename, i.lineno) i.sink = self for i in outputs.values(): if i.source is not None: raise C2CHIPError("%s has already has a source" % (i.name, i.filename, i.lineno)) i.source = self for i in inputs.keys(): if i not in component_inputs: raise C2CHIPError( "%s is not an input of component %s" % (i, component_name), i.filename, i.lineno) for i in outputs.keys(): if i not in component_outputs: raise C2CHIPError( "%s is not an output of component %s" % (i, component_name), i.filename, i.lineno)
def generate_verilog(self): """ Synopsis: .. code-block:: python chip.generate_verilog(name) Description: Generate synthesisable Verilog output. Arguments: None Returns: None """ for component in self.components.values(): component.generate_verilog() for i in self.wires: if i.source is None: raise C2CHIPError("wire %s has no source" % i.name, i.filename, i.lineno) if i.sink is None: raise C2CHIPError("wire %s has no sink" % i.name, i.filename, i.lineno) for i in self.inputs.values(): if i.sink is None: raise C2CHIPError("input %s has no sink" % i.name, i.filename, i.lineno) for i in self.outputs.values(): if i.source is None: raise C2CHIPError("output %s has no source" % i.name, i.filename, i.lineno) ports = ["clk", "rst", "exception"] ports += ["%s" % i.name for i in self.inputs.values()] ports += ["%s_stb" % i.name for i in self.inputs.values()] ports += ["%s_ack" % i.name for i in self.inputs.values()] ports += ["%s" % i.name for i in self.outputs.values()] ports += ["%s_stb" % i.name for i in self.outputs.values()] ports += ["%s_ack" % i.name for i in self.outputs.values()] ports = ", ".join(ports) output_file = open(self.name + ".v", "w") output_file.write("module %s(%s);\n" % (self.name, ports)) output_file.write(" input clk;\n") output_file.write(" input rst;\n") output_file.write(" output exception;\n") for i in self.inputs.values(): output_file.write(" input [31:0] %s;\n" % i.name) output_file.write(" input %s_stb;\n" % i.name) output_file.write(" output %s_ack;\n" % i.name) for i in self.outputs.values(): output_file.write(" output [31:0] %s;\n" % i.name) output_file.write(" output %s_stb;\n" % i.name) output_file.write(" input %s_ack;\n" % i.name) for i in self.wires: output_file.write(" wire [31:0] %s;\n" % i.name) output_file.write(" wire %s_stb;\n" % i.name) output_file.write(" wire %s_ack;\n" % i.name) for instance in self.instances: output_file.write(" wire exception_%s;\n" % (id(instance))) for instance in self.instances: component = instance.component_name output_file.write(" %s %s_%s(\n " % (component, component, id(instance))) ports = [] ports.append(".clk(clk)") ports.append(".rst(rst)") ports.append(".exception(exception_%s)" % id(instance)) for name, i in instance.inputs.iteritems(): ports.append(".input_%s(%s)" % (name, i.name)) ports.append(".input_%s_stb(%s_stb)" % (name, i.name)) ports.append(".input_%s_ack(%s_ack)" % (name, i.name)) for name, i in instance.outputs.iteritems(): ports.append(".output_%s(%s)" % (name, i.name)) ports.append(".output_%s_stb(%s_stb)" % (name, i.name)) ports.append(".output_%s_ack(%s_ack)" % (name, i.name)) output_file.write(",\n ".join(ports)) output_file.write(");\n") output_file.write( " assign exception = %s;\n" % (" || ".join(["exception_" + str(id(i)) for i in self.instances]))) output_file.write("endmodule\n") output_file.close()
def generate_verilog(self): """Generate verilog for the chip""" for i in self.wires: if i.source is None: raise C2CHIPError("wire %s has no source"%i.name) if i.sink is None: raise C2CHIPError("wire %s has no sink"%i.name) for i in self.inputs: if i.sink is None: raise C2CHIPError("input %s has no sink"%i.name) for i in self.outputs: if i.source is None: raise C2CHIPError("output %s has no source"%i.name) ports = ["clk", "rst"] ports += ["%s"%i.name for i in self.inputs] ports += ["%s_stb"%i.name for i in self.inputs] ports += ["%s_ack"%i.name for i in self.inputs] ports += ["%s"%i.name for i in self.outputs] ports += ["%s_stb"%i.name for i in self.outputs] ports += ["%s_ack"%i.name for i in self.outputs] ports = ", ".join(ports) output_file = open(self.name + ".v", "w") output_file.write("module %s(%s);\n"%(self.name, ports)) output_file.write(" input clk;\n") output_file.write(" input rst;\n") for i in self.inputs: output_file.write(" input [15:0] %s;\n"%i.name) output_file.write(" input %s_stb;\n"%i.name) output_file.write(" output %s_ack;\n"%i.name) for i in self.outputs: output_file.write(" output [15:0] %s;\n"%i.name) output_file.write(" output %s_stb;\n"%i.name) output_file.write(" input %s_ack;\n"%i.name) for i in self.wires: output_file.write(" wire [15:0] %s;\n"%i.name) output_file.write(" wire %s_stb;\n"%i.name) output_file.write(" wire %s_ack;\n"%i.name) for instance in self.instances: component = instance.component.name output_file.write(" %s %s_%s(\n "%(component, component, id(instance))) ports = [] ports.append(".clk(clk)") ports.append(".rst(rst)") for name, i in instance.inputs.iteritems(): ports.append(".input_%s(%s)"%(name, i.name)) ports.append(".input_%s_stb(%s_stb)"%(name, i.name)) ports.append(".input_%s_ack(%s_ack)"%(name, i.name)) for name, i in instance.outputs.iteritems(): ports.append(".output_%s(%s)"%(name, i.name)) ports.append(".output_%s_stb(%s_stb)"%(name, i.name)) ports.append(".output_%s_ack(%s_ack)"%(name, i.name)) output_file.write(",\n ".join(ports)) output_file.write(");\n") output_file.write("endmodule\n") output_file.close()
def scan(self, filename, input_file=None): """Convert the test file into tokens""" self.filename = filename if input_file is None: try: input_file = open(self.filename) except IOError: raise C2CHIPError("Cannot open file: "+self.filename) token = [] tokens = [] self.lineno = 1 for line in input_file: #include files line = line+" " if line.strip().startswith("#include"): filename = self.filename lineno = self.lineno self.tokens.extend(tokens) directory = os.path.abspath(self.filename) directory = os.path.dirname(directory) if line.strip().endswith(">"): self.filename = "library" library = line.strip().split("<")[1].strip(' ><"') self.scan(self.filename, StringIO.StringIO(libs[library])) else: self.filename = line.strip().replace("#include", "").strip(' ><"') self.filename = os.path.join(directory, self.filename) self.scan(self.filename) self.lineno = lineno self.filename = filename tokens = [] continue newline = True for char in line: if not token: token = char #c style comment elif (token + char).startswith("/*"): if (token + char).endswith("*/"): token = "" else: token += char #c++ style comment elif token.startswith("//"): if newline: token = char else: token += char #identifier elif token[0].isalpha(): if char.isalnum() or char== "_": token += char else: tokens.append((self.filename, self.lineno, token)) token = char #number elif token[0].isdigit(): if char.upper() in "UXABCDEFL0123456789.": token += char else: tokens.append((self.filename, self.lineno, token)) token = char #string literal elif token.startswith('"'): if char == '"' and previous_char != "\\": token += char tokens.append((self.filename, self.lineno, token)) token = "" else: #remove dummy space from the end of a line if newline: token = token[:-1] previous_char = char token += char #character literal elif token.startswith("'"): if char == "'": token += char tokens.append((self.filename, self.lineno, token)) token = "" else: token += char #operator elif token in operators: if token + char in operators: token += char else: tokens.append((self.filename, self.lineno, token)) token = char else: token = char newline = False self.lineno += 1 self.tokens.extend(tokens)
def error(self, string): """Generate an error message (including the filename and line number)""" raise C2CHIPError(string + "\n", self.filename, self.lineno)
def scan(self, filename, input_file=None, parameters={}, external_preprocessor=True): """Convert the test file into tokens""" self.filename = filename if external_preprocessor: directory = os.path.abspath(__file__) directory = os.path.dirname(directory) directory = os.path.join(directory, "include") cpp_commands = [ "cpp", "-nostdinc", "-isystem", directory, filename] pipe = subprocess.Popen(cpp_commands, stdout=subprocess.PIPE) input_file = pipe.stdout else: if input_file is None: try: input_file = open(self.filename) except IOError: raise C2CHIPError("Cannot open file: " + self.filename) token = [] tokens = [] self.lineno = 1 jump = False for line in input_file: # include files line = line + " " if jump: if line.strip().startswith("#endif"): jump = False if line.strip().startswith("#else"): jump = False self.lineno += 1 continue elif external_preprocessor and line.strip().startswith("#"): l = line.strip() l = l.lstrip("#") l = l.split('"') lineno = int(l[0].strip()) self.lineno = lineno filename = l[1].strip().strip('"') self.filename = filename continue elif line.strip().startswith("#include"): filename = self.filename lineno = self.lineno self.tokens.extend(tokens) if line.strip().endswith(">"): directory = os.path.abspath(__file__) directory = os.path.dirname(directory) directory = os.path.join(directory, "include") else: directory = os.path.abspath(self.filename) directory = os.path.dirname(directory) self.filename = line.strip().replace( "#include", "").strip(' ><"') self.filename = os.path.join(directory, self.filename) self.scan(self.filename) self.lineno = lineno self.filename = filename tokens = [] self.lineno += 1 continue elif line.strip().startswith("#define"): definition = line.strip().split(" ")[1] self.definitions.append(definition) self.lineno += 1 continue elif line.strip().startswith("#undef"): definition = line.strip().split(" ")[1] self.definitions.remove(definition) self.lineno += 1 continue elif line.strip().startswith("#ifdef"): definition = line.strip().split(" ")[1] if definition not in self.definitions: jump = True self.lineno += 1 continue elif line.strip().startswith("#ifndef"): definition = line.strip().split(" ")[1] if definition in self.definitions: jump = True self.lineno += 1 continue elif line.strip().startswith("#else"): jump = True self.lineno += 1 continue elif line.strip().startswith("#endif"): self.lineno += 1 continue newline = True for char in line: if not token: token = char # c style comment elif (token + char).startswith("/*"): if (token + char).endswith("*/"): token = "" else: token += char # c++ style comment elif token.startswith("//"): if newline: token = char else: token += char # identifier elif token[0].isalpha(): if char.isalnum() or char == "_": token += char else: tokens.append((self.filename, self.lineno, token)) token = char # number elif token[0].isdigit(): if char.upper() in "0123456789ABCDEFXUL.": token += char elif token.upper().endswith("E") and char in ["+", "-"]: token += char else: tokens.append((self.filename, self.lineno, token)) token = char # string literal elif token.startswith('"'): if char == '"' and previous_char != "\\": token += char tokens.append((self.filename, self.lineno, token)) token = "" else: # remove dummy space from the end of a line if newline: token = token[:-1] previous_char = char token += char # character literal elif token.startswith("'"): if char == "'": token += char tokens.append((self.filename, self.lineno, token)) token = "" else: token += char # operator elif token in operators: if token + char in operators: token += char else: tokens.append((self.filename, self.lineno, token)) token = char else: token = char newline = False self.lineno += 1 self.tokens.extend(tokens)