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

Subversion Repositories tcp_socket

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /tcp_socket/trunk/chips2
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/README.rst
4,29 → 4,49
Introduction
------------
 
Chips is a fast and simple way to design Logic Devices. You can think of
a Chips design as a network on a chip. Many C Programs are all executing in
parallel, streaming data between each other using fast on-chip connections.
*Chips* makes FPGA design quicker and easier. *Chips* isn't an HDL like VHDL or
Verilog, its a different way of doing things. In *Chips*, you design components
using a simple subset of the C programming language. There's a Python API to
connect C components together using fast data streams to form complex, parallel
systems all in a single chip. You don't need to worry about clocks, resets,
or timing. You don't need to follow special templates to make your code
synthesisable. All that's done for you!
 
The interface is simple, design components using C, and connect them together
to form a chip using a simple python API. Behind the scenes, chips will comvert
C programs into efficient verilog implementation based on interconnected Finite
State Machines, or custom CPUs.
 
Test
----
$ cd test_suite
$ test_c2verilog
 
::
 
$ cd test_suite
$ test_c2verilog
 
Install
-------
$ sudo python setup install
 
::
 
$ sudo python setup install
 
Documentation
-------------
 
::
 
$ cd docs
$ make html
 
To Prepare a Source Distribution
--------------------------------
$ python setup sdist
 
::
 
$ python setup sdist
 
Distribution is contained in ./dist
 
To Create a Windows Distribution
--------------------------------
$ python setup bdist_wininst
 
::
 
$ python setup bdist_wininst
/chips/api/api.py
7,7 → 7,7
 
"""A Chip represents a collection of components connected together by
wires. As you create wires and component instances, you will need to tell
them which chip they belong to. Once you have a completed chip you can:
them which chip they belong to. Once you have a completed chip you can:
 
+ Implement it in verilog - using the generate_verilog method
+ Automatically generate documentation - using the generate_document method
155,10 → 155,9
 
os.system("iverilog -o %s %s"%(self.name + "_tb", files))
if run:
return os.system("vvp %s"%(self.name + "_tb"))
return os.system("vvp %s"%(self.name + "_tb"))
 
 
 
class Component:
 
"""You can use the component class to add new components to your chip.
166,7 → 165,7
component when you create it. The Chips API will automatically compile the
C code, and extract the name, inputs, outputs and the documentation from the
code.
 
If you want to keep the C file seperate you can read it in from a file like
this::
 
174,7 → 173,7
 
Once you have defined a component you can use the __call__ method to create
an instance of the component.
 
"""
 
def __init__(self, C_file):
192,11 → 191,33
return _Instance(self, chip, inputs, outputs)
 
 
class VerilogComponent(Component):
 
"""You can use the component class to add new components to your chip.
This version of Component allows components to be written directly in verilog.
 
my_component = Adder("adder", inputs = ["a", "b"], outputs = ["z"])
 
Once you have defined a component you can use the __call__ method to create
an instance of the component.
 
"""
 
def __init__(self, name, inputs, outputs, docs):
 
"""Takes a single string argument, the C code to compile"""
 
self.name = name
self.inputs = inputs
self.outputs = outputs
self.docs = docs
 
 
class _Instance:
 
"""This class represents a component instance. You don't normaly need to
create them directly, use the Component.__call__ method."""
 
def __init__(self, component, chip, inputs, outputs):
self.chip = chip
self.inputs = inputs
chips/api Property changes : Added: svn:ignore ## -0,0 +1 ## +*.bak Index: chips/compiler/builtins.py =================================================================== --- chips/compiler/builtins.py (revision 3) +++ chips/compiler/builtins.py (revision 4) @@ -101,7 +101,7 @@ long unsigned long_unsigned_modulo_xxxx(long unsigned dividend, long unsigned divisor){ long_unsigned_divide_xxxx(dividend, divisor); - return long_unsigned_modulo_yyyy; + return long_unsigned_modulo_yyyy; } long int long_modulo_xxxx(long int dividend, long int divisor){ @@ -117,4 +117,64 @@ return modulo; } +int float_equal_xxxx(long int a, long int b){ + if (a < 0) { + a = 0x80000000ul - a; + } + if (b < 0) { + b = 0x80000000ul - b; + } + return a == b; +} + +int float_ne_xxxx(long int a, long int b){ + if (a < 0) { + a = 0x80000000ul - a; + } + if (b < 0) { + b = 0x80000000ul - b; + } + return a != b; +} + +int float_lt_xxxx(long int a, long int b){ + if (a < 0) { + a = 0x80000000ul - a; + } + if (b < 0) { + b = 0x80000000ul - b; + } + return a < b; +} + +int float_gt_xxxx(long int a, long int b){ + if (a < 0) { + a = 0x80000000ul - a; + } + if (b < 0) { + b = 0x80000000ul - b; + } + return a > b; +} + +int float_le_xxxx(long int a, long int b){ + if (a < 0) { + a = 0x80000000ul - a; + } + if (b < 0) { + b = 0x80000000ul - b; + } + return a <= b; +} + +int float_ge_xxxx(long int a, long int b){ + if (a < 0) { + a = 0x80000000ul - a; + } + if (b < 0) { + b = 0x80000000ul - b; + } + return a >= b; +} + """
/chips/compiler/parse_tree.py
2,671 → 2,1157
__copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
__version__ = "0.1"
 
import struct
 
class NotConstant(Exception):
pass
pass
 
def value(expression):
 
"""If an expression can be evaluated at compile time, return the value"""
def constant_fold(expression):
 
if hasattr(expression, "value"):
return truncate(expression.value())
else:
raise NotConstant
"""Replace an expression with a constant if possible"""
 
def constant_fold(expression):
try:
return Constant(expression.value(), expression.type_(), expression.size(), expression.signed())
except NotConstant:
return expression
 
"""Replace an expression with a constant if possible"""
 
try:
return Constant(value(expression))
except NotConstant:
return expression
class Process:
 
def truncate(number):
def generate(self):
instructions = []
for function in self.functions:
if hasattr(function, "declarations"):
instructions.extend(function.generate())
 
"""Truncate arithmetic results to the target number of bits"""
instructions.append(
{"op" :"jmp_and_link",
"dest" :self.main.return_address,
"label":"function_%s"%id(self.main)})
 
#sign = number & 0x10000
#number = number & 0xffff
#if sign:
#number = ~0xffff | number
return int(number)
instructions.append(
{"op":"stop"})
 
class Process:
def generate(self):
instructions = []
for function in self.functions:
if hasattr(function, "declarations"):
instructions.extend(function.generate())
instructions.append({"op" :"jmp_and_link",
"dest" :self.main.return_address,
"label":"function_%s"%id(self.main)})
instructions.append({"op":"stop"})
for function in self.functions:
if not hasattr(function, "declarations"):
instructions.extend(function.generate())
return instructions
for function in self.functions:
if not hasattr(function, "declarations"):
instructions.extend(function.generate())
return instructions
 
 
class Function:
def generate(self):
instructions = []
instructions.append({"op":"label", "label":"function_%s"%id(self)})
instructions.extend(self.statement.generate())
if not hasattr(self, "return_value"):
instructions.append({"op":"jmp_to_reg", "src":self.return_address})
return instructions
 
def generate(self):
instructions = []
instructions.append({"op":"label", "label":"function_%s"%id(self)})
instructions.extend(self.statement.generate())
if not hasattr(self, "return_value"):
instructions.append({"op":"jmp_to_reg", "src":self.return_address})
return instructions
 
 
class Break:
def generate(self): return [{"op":"goto", "label":"break_%s"%id(self.loop)}]
 
def generate(self): return [
{"op":"goto", "label":"break_%s"%id(self.loop)}]
 
 
class Continue:
def generate(self): return [{"op":"goto", "label":"continue_%s"%id(self.loop)}]
 
def generate(self): return [
{"op":"goto", "label":"continue_%s"%id(self.loop)}]
 
 
class Assert:
def generate(self):
result = self.allocator.new(self.expression.size)
instructions = self.expression.generate(result)
self.allocator.free(result)
instructions.append({"op":"assert", "src":result, "line":self.line, "file":self.filename})
return instructions
 
def generate(self):
result = self.allocator.new(self.expression.size())
instructions = self.expression.generate(result, self.allocator)
self.allocator.free(result)
 
instructions.append(
{"op":"assert",
"src":result,
"line":self.line,
"file":self.filename})
 
return instructions
 
 
class Return:
def generate(self):
if hasattr(self, "expression"):
instructions = self.expression.generate(self.function.return_value)
else:
instructions = []
instructions.append({"op":"jmp_to_reg", "src":self.function.return_address})
return instructions
 
def generate(self):
if hasattr(self, "expression"):
 
result = self.allocator.new(self.function.size)
instructions=self.function.return_value.copy(
self.expression,
result,
self.allocator)
self.allocator.free(result)
 
else:
instructions = []
 
instructions.append(
{"op":"jmp_to_reg",
"src":self.function.return_address})
 
return instructions
 
 
class Report:
def generate(self):
result = self.allocator.new(self.expression.size)
instructions = self.expression.generate(result)
self.allocator.free(result)
instructions.append({"op":"report",
"src":result,
"line":self.line,
"file":self.filename,
"signed":self.expression.signed})
return instructions
 
def generate(self):
result = self.allocator.new(self.expression.size())
instructions = self.expression.generate(result, self.allocator)
self.allocator.free(result)
 
instructions.append(
{"op":"report",
"src":result,
"line":self.line,
"file":self.filename,
"type":self.expression.type_(),
"signed":self.expression.signed()})
 
return instructions
 
 
class WaitClocks:
def generate(self):
result = self.allocator.new(self.expression.size)
instructions = self.expression.generate(result)
self.allocator.free(result)
instructions.append({"op":"wait_clocks", "src":result})
return instructions
 
def generate(self):
result = self.allocator.new(self.expression.size())
instructions = self.expression.generate(result, self.allocator)
self.allocator.free(result)
instructions.append({"op":"wait_clocks", "src":result})
return instructions
 
 
class If:
def generate(self):
try:
if value(self.expression):
return self.true_statement.generate()
else:
if self.false_statement:
return self.false_statement.generate()
else:
return []
except NotConstant:
result = self.allocator.new(self.expression.size)
instructions = []
instructions.extend(self.expression.generate(result))
instructions.append({"op" :"jmp_if_false",
"src" :result,
"label":"else_%s"%id(self)})
self.allocator.free(result)
instructions.extend(self.true_statement.generate())
instructions.append({"op":"goto", "label":"end_%s"%id(self)})
instructions.append({"op":"label", "label":"else_%s"%id(self)})
if self.false_statement:
instructions.extend(self.false_statement.generate())
instructions.append({"op":"label", "label":"end_%s"%id(self)})
return instructions
 
def generate(self):
 
try:
 
if self.expression.value():
return self.true_statement.generate()
else:
if self.false_statement:
return self.false_statement.generate()
else:
return []
 
except NotConstant:
 
result = self.allocator.new(self.expression.size())
instructions = []
instructions.extend(self.expression.generate(result, self.allocator))
 
instructions.append(
{"op" : "jmp_if_false",
"src" : result,
"label" : "else_%s"%id(self)})
 
self.allocator.free(result)
instructions.extend(self.true_statement.generate())
instructions.append({"op":"goto", "label":"end_%s"%id(self)})
instructions.append({"op":"label", "label":"else_%s"%id(self)})
if self.false_statement:
instructions.extend(self.false_statement.generate())
instructions.append({"op":"label", "label":"end_%s"%id(self)})
return instructions
 
 
class Switch:
def generate(self):
result = self.allocator.new(self.expression.size)
test = self.allocator.new(self.expression.size)
instructions = self.expression.generate(result)
for value, case in self.cases.iteritems():
instructions.append({"op":"==", "dest":test, "src":result, "right":value, "signed":True})
instructions.append({"op":"jmp_if_true", "src":test, "label":"case_%s"%id(case)})
if hasattr(self, "default"):
instructions.append({"op":"goto", "label":"case_%s"%id(self.default)})
self.allocator.free(result)
self.allocator.free(test)
instructions.extend(self.statement.generate())
instructions.append({"op":"label", "label":"break_%s"%id(self)})
return instructions
 
def generate(self):
result = self.allocator.new(self.expression.size())
test = self.allocator.new(self.expression.size())
instructions = self.expression.generate(result, self.allocator)
for value, case in self.cases.iteritems():
 
instructions.append(
{"op":"==",
"dest":test,
"src":result,
"right":value,
"size": self.expression.size(),
"signed":True})
 
instructions.append(
{"op":"jmp_if_true",
"src":test,
"label":"case_%s"%id(case)})
 
if hasattr(self, "default"):
 
instructions.append(
{"op":"goto",
"label":"case_%s"%id(self.default)})
 
self.allocator.free(result)
self.allocator.free(test)
instructions.extend(self.statement.generate())
instructions.append({"op":"label", "label":"break_%s"%id(self)})
return instructions
 
 
class Case:
def generate(self):
return [{"op":"label", "label":"case_%s"%id(self)}]
 
def generate(self):
return [{"op":"label", "label":"case_%s"%id(self)}]
 
 
class Default:
def generate(self):
return [{"op":"label", "label":"case_%s"%id(self)}]
 
def generate(self):
return [{"op":"label", "label":"case_%s"%id(self)}]
 
 
class Loop:
def generate(self):
instructions = [{"op":"label", "label":"begin_%s"%id(self)}]
instructions.append({"op":"label", "label":"continue_%s"%id(self)})
instructions.extend(self.statement.generate())
instructions.append({"op":"goto", "label":"begin_%s"%id(self)})
instructions.append({"op":"label", "label":"break_%s"%id(self)})
return instructions
 
def generate(self):
instructions = [{"op":"label", "label":"begin_%s"%id(self)}]
instructions.append({"op":"label", "label":"continue_%s"%id(self)})
instructions.extend(self.statement.generate())
instructions.append({"op":"goto", "label":"begin_%s"%id(self)})
instructions.append({"op":"label", "label":"break_%s"%id(self)})
return instructions
 
 
class For:
def generate(self):
instructions = []
if hasattr(self, "statement1"):
instructions.extend(self.statement1.generate())
instructions.append({"op":"label", "label":"begin_%s"%id(self)})
if hasattr(self, "expression"):
result = self.allocator.new(self.expression.size)
instructions.extend(self.expression.generate(result))
instructions.append({"op":"jmp_if_false", "src":result, "label":"end_%s"%id(self)})
self.allocator.free(result)
instructions.extend(self.statement3.generate())
instructions.append({"op":"label", "label":"continue_%s"%id(self)})
if hasattr(self, "statement2"):
instructions.extend(self.statement2.generate())
instructions.append({"op":"goto", "label":"begin_%s"%id(self)})
instructions.append({"op":"label", "label":"end_%s"%id(self)})
instructions.append({"op":"label", "label":"break_%s"%id(self)})
return instructions
 
def generate(self):
instructions = []
if hasattr(self, "statement1"):
instructions.extend(self.statement1.generate())
instructions.append({"op":"label", "label":"begin_%s"%id(self)})
if hasattr(self, "expression"):
result = self.allocator.new(self.expression.size())
 
instructions.extend(
self.expression.generate(result, self.allocator))
 
instructions.append(
{"op":"jmp_if_false",
"src":result,
"label":"end_%s"%id(self)})
 
self.allocator.free(result)
instructions.extend(self.statement3.generate())
instructions.append({"op":"label", "label":"continue_%s"%id(self)})
if hasattr(self, "statement2"):
instructions.extend(self.statement2.generate())
instructions.append({"op":"goto", "label":"begin_%s"%id(self)})
instructions.append({"op":"label", "label":"end_%s"%id(self)})
instructions.append({"op":"label", "label":"break_%s"%id(self)})
return instructions
 
 
class Block:
def generate(self):
instructions = []
for statement in self.statements:
instructions.extend(statement.generate())
return instructions
 
def generate(self):
instructions = []
for statement in self.statements:
instructions.extend(statement.generate())
return instructions
 
 
class CompoundDeclaration:
def __init__(self, declarations):
self.declarations = declarations
 
def generate(self):
instructions = []
for declaration in self.declarations:
instructions.extend(declaration.generate());
return instructions
def __init__(self, declarations):
self.declarations = declarations
 
def generate(self):
instructions = []
for declaration in self.declarations:
instructions.extend(declaration.generate());
return instructions
 
 
class VariableDeclaration:
def __init__(self, allocator, initializer, name, type_, size, signed):
self.initializer = initializer
self.allocator = allocator
self.type_ = type_
self.size = size
self.signed = signed
self.name = name
def instance(self):
register = self.allocator.new(self.size, "variable "+self.name)
return VariableInstance(register, self.initializer, self.type_, self.size, self.signed)
 
def __init__(self, allocator, initializer, name, type_, size, signed, const):
self.initializer = initializer
self.allocator = allocator
self._type = type_
self._size = size
self._signed = signed
self._const = const
self.name = name
 
def instance(self):
register = self.allocator.new(self.size(), "variable "+self.name)
 
return VariableInstance(
register,
self.initializer,
self.type_(),
self.size(),
self.signed(),
self.const(),
self.allocator)
 
def type_(self):
return self._type
 
def size(self):
return self._size
 
def signed(self):
return self._signed
 
def const(self):
return self._const
 
 
class VariableInstance:
def __init__(self, register, initializer, type_, size, signed):
self.register = register
self.type_ = type_
self.initializer = initializer
self.size = size
self.signed = signed
def generate(self):
return self.initializer.generate(self.register)
 
def __init__(self, register, initializer, type_, size, signed, const, allocator):
self.register = register
self._type = type_
self.initializer = initializer
self._size = size
self._signed = signed
self._const = const
self.allocator = allocator
 
def generate(self):
return self.initializer.generate(self.register, self.allocator)
 
def reference(self):
return Variable(self)
 
def type_(self):
return self._type
 
def size(self):
return self._size
 
def signed(self):
return self._signed
 
def const(self):
return self._const
 
 
class ArrayDeclaration:
def __init__(self,
allocator,
size,
type_,
element_type,
element_size,
element_signed,
initializer = None,
initialize_memory = False):
 
self.allocator = allocator
self.type_ = type_
self.size = size
self.signed = False
self.element_type = element_type
self.element_size = element_size
self.element_signed = element_signed
self.initializer = initializer
self.initialize_memory = initialize_memory
def __init__(self,
allocator,
size,
type_,
element_type,
element_size,
element_signed,
initializer = None,
initialize_memory = False):
 
def instance(self):
location = self.allocator.new_array(self.size, self.initializer, self.element_size)
register = self.allocator.new(2, "array")
return ArrayInstance(location,
register,
self.size,
self.type_,
self.initializer,
self.initialize_memory,
self.element_type,
self.element_size,
self.element_signed)
self.allocator = allocator
self._type = type_
self._size = size
self._signed = False
self.element_type = element_type
self.element_size = element_size
self.element_signed = element_signed
self.initializer = initializer
self.initialize_memory = initialize_memory
 
def instance(self):
 
location = self.allocator.new_array(
self.size(),
self.initializer,
self.element_size)
 
register = self.allocator.new(2, "array")
 
return ArrayInstance(
location,
register,
self.size(),
self.type_(),
self.initializer,
self.initialize_memory,
self.element_type,
self.element_size,
self.element_signed)
 
def type_(self):
return self._type
 
def size(self):
return self._size
 
def signed(self):
return self._signed
 
class ArrayInstance:
def __init__(self,
location,
register,
size,
type_,
initializer,
initialize_memory,
element_type,
element_size,
element_signed):
 
self.register = register
self.location = location
self.type_ = type_
self.size = size
self.signed = False
self.element_type = element_type
self.element_size = element_size
self.element_signed = element_signed
self.initializer = initializer
self.initialize_memory = initialize_memory
def __init__(self,
location,
register,
size,
type_,
initializer,
initialize_memory,
element_type,
element_size,
element_signed):
 
def generate(self, result=None):
instructions = []
#If initialize memory is true, the memory content will initialised (as at configuration time)
#If initialize memory is false, then the memory will need to be filled by the program.
if not self.initialize_memory and self.initializer is not None:
location = 0
for value in self.initializer:
instructions.append({
"op":"memory_write_literal",
"address":location,
"value":value,
"element_size":self.element_size
})
location += 1
instructions.append({
"op":"literal",
"literal":self.location,
"dest":self.register
})
#this bit here is to make string literals work,
#in this case an array instance is created implicitly,
#but the value of the expression is the array register.
if result is not None and result != self.register:
instructions.append({
"op" :"move",
"dest":result,
"src" :self.register
})
return instructions
self.register = register
self.location = location
self._type = type_
self._size = size * element_size
self._signed = False
self.element_type = element_type
self.element_size = element_size
self.element_signed = element_signed
self.initializer = initializer
self.initialize_memory = initialize_memory
 
def generate(self, result=None):
instructions = []
#If initialize memory is true, the memory content will initialised (as at configuration time)
#If initialize memory is false, then the memory will need to be filled by the program.
if not self.initialize_memory and self.initializer is not None:
location=self.location
for value in self.initializer:
 
instructions.append(
{"op":"memory_write_literal",
"address":location,
"value":value,
"element_size":self.element_size})
location += 1
 
instructions.append(
{"op":"literal",
"literal":self.location,
"dest":self.register})
 
return instructions
 
 
def reference(self):
return Array(self)
 
def type_(self):
return self._type
 
def size(self):
return self._size
 
def signed(self):
return self._signed
 
 
class StructDeclaration:
def __init__(self, members):
self.members = members
 
def instance(self):
instances = {}
for name, declaration in self.members.iteritems():
instances[name] = declaration.instance()
return StructInstance(instances)
def __init__(self, members):
self.members = members
self._type = "struct {%s}"%"; ".join(
[i.type_() for i in members.values()])
self._size = sum([i.size() for i in members.values()])
self._signed = False
 
def instance(self):
instances = {}
for name, declaration in self.members.iteritems():
instances[name] = declaration.instance()
return StructInstance(instances)
 
def type_(self):
return self._type
 
def size(self):
return self._size
 
def signed(self):
return self._signed
 
 
class StructInstance:
def __init__(self, members):
self.members = members
self.type_ = "struct"
 
def generate(self):
instructions = []
for member in self.members.values():
instructions.extend(member.generate())
return instructions
def __init__(self, members):
self.members = members
self._type = "struct {%s}"%"; ".join(
[i.type_() for i in members.values()])
self._size = sum([i.size() for i in members.values()])
self._signed = False
 
class Argument:
def __init__(self,
name,
type_,
size,
signed,
parser,
element_type,
element_size,
element_signed):
self.type_=type_
self.size=size
self.signed=signed
self.element_type = element_type
self.element_size = element_size
self.element_signed = element_signed
parser.scope[name] = self
self.register = parser.allocator.new(size, "function argument "+name)
def generate(self): return []
def generate(self):
instructions = []
for member in self.members.values():
instructions.extend(member.generate())
return instructions
 
def reference(self):
return Struct(self)
 
def type_(self):
return self._type
 
def size(self):
return self._size
 
def signed(self):
return self._signed
 
 
class DiscardExpression:
def __init__(self, expression, allocator):
self.expression = expression
self.allocator = allocator
 
def generate(self):
result = self.allocator.new(self.expression.size)
instructions = self.expression.generate(result)
self.allocator.free(result)
return instructions
def __init__(self, expression, allocator):
self.expression = expression
self.allocator = allocator
 
#...then Expressions...
def generate(self):
result = self.allocator.new(self.expression.size())
instructions = self.expression.generate(result, self.allocator)
self.allocator.free(result)
return instructions
 
#Expressions generate methods accept a result argument.
#This indicates which register to put the result in.
 
#Expressions may also provide a value method which returns the value of an xpression
#if it can be calculated at compile time.
class Expression:
 
def __init__(self, t, size, signed):
self.type_var=t
self.size_var=size
self.signed_var=signed
 
def type_(self):
return self.type_var
 
def size(self):
return self.size_var
 
def signed(self):
return self.signed_var
 
def value(self):
raise NotConstant
 
def const(self):
return True
 
def int_value(self):
if self.type_() == "float":
byte_value = struct.pack(">f", self.value())
value = ord(byte_value[0]) << 24
value |= ord(byte_value[1]) << 16
value |= ord(byte_value[2]) << 8
value |= ord(byte_value[3])
return value
else:
return self.value()
 
 
class Object(Expression):
 
def __init__(self, instance):
Expression.__init__(self, instance.type_(), instance.size(), instance.signed())
self.instance = instance
 
def value(self):
raise NotConstant
 
def const(self):
return False
 
 
def AND(left, right):
return ANDOR(left, right, "jmp_if_false")
return ANDOR(left, right, "jmp_if_false")
 
 
def OR(left, right):
return ANDOR(left, right, "jmp_if_true")
return ANDOR(left, right, "jmp_if_true")
 
class ANDOR:
def __init__(self, left, right, op):
self.left = constant_fold(left)
self.right = constant_fold(right)
self.op = op
self.type_ = "int"
self.size = left.size
self.signed = left.signed
 
def generate(self, result):
instructions = self.left.generate(result)
instructions.append({"op":self.op, "src":result, "label":"end_%s"%id(self)})
instructions.extend(self.right.generate(result))
instructions.append({"op":"label", "label":"end_%s"%id(self)})
return instructions
class ANDOR(Expression):
 
def value(self):
if self.op == "jmp_if_false":
return value(self.left) and value(self.right)
def __init__(self, left, right, op):
self.left = constant_fold(left)
self.right = constant_fold(right)
self.op = op
 
Expression.__init__(
self,
"int",
max(left.size(), right.size()),
left.signed() and right.signed())
 
def generate(self, result, allocator):
instructions = self.left.generate(result, allocator)
instructions.append({"op":self.op, "src":result, "label":"end_%s"%id(self)})
instructions.extend(self.right.generate(result, allocator))
instructions.append({"op":"label", "label":"end_%s"%id(self)})
return instructions
 
def value(self):
if self.op == "jmp_if_false":
return self.left.value() and self.right.value()
else:
return self.left.value() or self.right.value()
 
 
def get_binary_type(left, right, operator):
"""
Given the type of the left and right hand operators, determine the type
of the resulting value.
"""
 
binary_types = {
"float,float,+" : ("float", 4, True),
"float,float,-" : ("float", 4, True),
"float,float,*" : ("float", 4, True),
"float,float,/" : ("float", 4, True),
"float,float,==" : ("int", 4, True),
"float,float,!=" : ("int", 4, True),
"float,float,<" : ("int", 4, True),
"float,float,>" : ("int", 4, True),
"float,float,<=" : ("int", 4, True),
"float,float,>=" : ("int", 4, True)}
 
signature = ",".join([left.type_(), right.type_(), operator])
if signature in binary_types:
type_, size, signed = binary_types[signature]
else:
return value(self.left) or value(self.right)
type_ = left.type_()
size = max(left.size(), right.size())
signed = left.signed() and right.signed()
 
class Binary:
def __init__(self, operator, left, right, allocator):
self.left = constant_fold(left)
self.right = constant_fold(right)
self.operator = operator
self.allocator = allocator
self.type_ = self.left.type_
self.size = max(left.size, right.size)
self.signed = left.signed and right.signed
return type_, size, signed
 
def generate(self, result):
new_register = self.allocator.new(self.size)
try:
instructions = self.right.generate(new_register)
instructions.append({"op" :self.operator,
"dest":result,
"left":value(self.left),
"src":new_register,
"signed":self.signed})
except NotConstant:
try:
instructions = self.left.generate(new_register)
instructions.append({"op" :self.operator,
"dest" :result,
"src" :new_register,
"right":value(self.right),
"signed" :self.signed})
except NotConstant:
instructions = self.left.generate(new_register)
right = self.allocator.new(self.right.size)
instructions.extend(self.right.generate(right))
instructions.append({"op" :self.operator,
"dest":result,
"src" :new_register,
"srcb":right,
"signed":self.signed})
self.allocator.free(right)
self.allocator.free(new_register)
return instructions
class Binary(Expression):
 
def value(self):
return eval("%s %s %s"%(value(self.left), self.operator, value(self.right)))
def __init__(self, operator, left, right):
self.left = constant_fold(left)
self.right = constant_fold(right)
self.operator = operator
type_, size, signed = get_binary_type(left, right, operator)
 
Expression.__init__(
self,
type_,
size,
signed)
 
def generate(self, result, allocator):
new_register = allocator.new(self.size())
try:
instructions = self.right.generate(new_register, allocator)
 
instructions.append(
{"op" :self.operator,
"dest":result,
"left":self.left.int_value(),
"src":new_register,
"type":self.type_(),
"size":self.size(),
"signed":self.signed()})
 
except NotConstant:
try:
instructions = self.left.generate(new_register, allocator)
 
instructions.append(
{"op" :self.operator,
"dest" :result,
"src" :new_register,
"right":self.right.int_value(),
"type":self.type_(),
"size":self.size(),
"signed" :self.signed()})
 
except NotConstant:
instructions = self.left.generate(new_register, allocator)
right = allocator.new(self.size())
instructions.extend(self.right.generate(right, allocator))
 
instructions.append(
{"op" :self.operator,
"dest":result,
"src" :new_register,
"srcb":right,
"type":self.type_(),
"size":self.size(),
"signed":self.signed()})
 
allocator.free(right)
allocator.free(new_register)
return instructions
 
def value(self):
 
if self.type_() == "int":
 
return int(eval("%s %s %s"%(
self.left.value(),
self.operator,
self.right.value())))
 
else:
 
return float(eval("%s %s %s"%(
self.left.value(),
self.operator,
self.right.value())))
 
 
 
def SizeOf(expression):
return Constant(expression.size)
return Constant(expression.size())
 
class Unary:
def __init__(self, operator, expression, allocator):
self.expression = constant_fold(expression)
self.operator = operator
self.type_ = self.expression.type_
self.size = expression.size
self.signed = expression.signed
self.allocator = allocator
 
def generate(self, result):
new_register = self.allocator.new(self.size)
instructions = self.expression.generate(new_register)
instructions.extend([{"op":self.operator, "dest":result, "src":new_register}])
self.allocator.free(new_register)
return instructions
class IntToFloat(Expression):
 
def value(self):
return eval("%s%s"%(self.operator, value(self.expression)))
def __init__(self, expression):
self.expression = constant_fold(expression)
 
class FunctionCall:
def generate(self, result):
instructions = []
for expression, argument in zip(self.arguments, self.function.arguments):
instructions.extend(expression.generate(argument.register))
instructions.append({"op" :"jmp_and_link",
"dest" :self.function.return_address,
"label":"function_%s"%id(self.function)})
if hasattr(self.function, "return_value"):
instructions.append({"op" :"move",
"dest" :result,
"src" :self.function.return_value})
return instructions
Expression.__init__( self, "float", 4, True)
 
class Output:
def __init__(self, name, expression):
self.name = name
self.expression = expression
self.type_ = "int"
self.size = expression.size
def generate(self, result, allocator):
new_register = allocator.new(self.size())
instructions = self.expression.generate(new_register, allocator)
 
def generate(self, result):
instructions = self.expression.generate(result);
instructions.append({"op" :"write", "src" :result, "output":self.name})
return instructions
instructions.extend([
{"op" : "int_to_float",
"dest" : result,
"src" : new_register}])
 
class FileWrite:
def __init__(self, name, expression):
self.name = name
self.expression = expression
self.type_ = "int"
self.size = expression.size
allocator.free(new_register)
return instructions
 
def generate(self, result):
instructions = self.expression.generate(result);
instructions.append({"op" :"file_write", "src" :result, "file_name":self.name})
return instructions
def value(self):
return float(self.expression.value())
 
class Input:
def __init__(self, name):
self.name = name
self.type_ = "int"
self.size = 2
self.signed = True
 
def generate(self, result):
return [{"op" :"read", "dest" :result, "input":self.name}]
class FloatToInt(Expression):
 
class FileRead:
def __init__(self, name):
self.name = name
self.type_ = "int"
self.size = 2
self.signed = True
def __init__(self, expression):
self.expression = constant_fold(expression)
 
def generate(self, result):
return [{"op" :"file_read", "dest" :result, "file_name":self.name}]
Expression.__init__( self, "int", 4, True)
 
class Ready:
def __init__(self, name):
self.name = name
self.type_ = "int"
self.size = 2
self.signed = True
def generate(self, result, allocator):
new_register = allocator.new(self.size())
instructions = self.expression.generate(new_register, allocator)
 
def generate(self, result):
return [{"op" :"ready", "dest" :result, "input":self.name}]
instructions.extend([
{"op" : "float_to_int",
"dest" : result,
"src" : new_register}])
 
class Array:
def __init__(self, declaration, allocator):
self.declaration = declaration
self.allocator = allocator
self.storage = "register"
self.type_ = self.declaration.type_
self.size = int(self.declaration.size) * 2
self.signed = False
allocator.free(new_register)
return instructions
 
def generate(self, result):
instructions = []
if result != self.declaration.register:
instructions.append({"op" :"move",
"dest":result,
"src" :self.declaration.register})
return instructions
def value(self):
return int(self.expression.value())
 
class ArrayIndex:
def __init__(self, declaration, index_expression, allocator):
self.declaration = declaration
self.allocator = allocator
self.index_expression = index_expression
self.storage = "memory"
self.type_ = self.declaration.element_type
self.size = self.declaration.element_size
self.signed = self.declaration.element_signed
 
def generate(self, result):
instructions = []
offset = self.allocator.new(2)
address = self.allocator.new(2)
instructions.extend(self.index_expression.generate(offset))
instructions.append({"op" :"+",
"dest" :address,
"src" :offset,
"srcb" :self.declaration.register,
"signed":False})
instructions.append({"op" :"memory_read_request",
"src" :address,
"sequence": id(self),
"element_size":self.size})
instructions.append({"op" :"memory_read_wait",
"src" :address,
"sequence": id(self),
"element_size":self.size})
instructions.append({"op" :"memory_read",
"src" :address,
"dest" :result,
"sequence": id(self),
"element_size":self.size})
self.allocator.free(address)
self.allocator.free(offset)
return instructions
class Unary(Expression):
 
class Variable:
def __init__(self, declaration, allocator):
self.declaration = declaration
self.allocator = allocator
self.storage = "register"
self.type_ = self.declaration.type_
self.size = self.declaration.size
self.signed = self.declaration.signed
def __init__(self, operator, expression):
self.expression = constant_fold(expression)
self.operator = operator
 
def generate(self, result):
instructions = []
if result != self.declaration.register:
instructions.append({"op" :"move",
"dest":result,
"src" :self.declaration.register})
return instructions
Expression.__init__(
self,
expression.type_(),
expression.size(),
expression.signed())
 
class PostIncrement:
def __init__(self, operator, lvalue, allocator):
self.operator = operator
self.lvalue = lvalue
self.allocator = allocator
self.type_ = self.lvalue.declaration.type_
self.size = self.lvalue.declaration.size
self.signed = self.lvalue.declaration.signed
def generate(self, result, allocator):
new_register = allocator.new(self.size())
instructions = self.expression.generate(new_register, allocator)
 
def generate(self, result):
instructions.extend([
{"op":self.operator,
"dest":result,
"src":new_register}])
 
instructions = []
allocator.free(new_register)
return instructions
 
instructions.append({"op" :"move",
"src" :self.lvalue.declaration.register,
"dest" :result})
def value(self):
return eval("%s%s"%(self.operator, self.expression.value()))
 
instructions.append({"op" :self.operator,
"dest" :self.lvalue.declaration.register,
"right" :1,
"src" :self.lvalue.declaration.register,
"signed":self.signed})
return instructions
 
class Assignment:
def __init__(self, lvalue, expression, allocator):
self.lvalue = lvalue
self.expression = expression
self.allocator = allocator
self.type_ = self.lvalue.type_
self.size = self.lvalue.size
self.signed = self.lvalue.signed
class FunctionCall(Expression):
 
def generate(self, result):
instructions = self.expression.generate(result)
if self.lvalue.storage == "register":
if result != self.lvalue.declaration.register:
instructions.append({"op" : "move",
"dest" : self.lvalue.declaration.register,
"src" : result})
def __init__(self, function):
self.function = function
 
elif self.lvalue.storage == "memory":
index = self.allocator.new(2)
address = self.allocator.new(2)
instructions.extend(self.lvalue.index_expression.generate(index))
instructions.append({"op" :"+",
"dest" :address,
"src" :index,
"srcb" :self.lvalue.declaration.register,
"signed" :self.signed})
instructions.append({"op" :"memory_write",
"src" :address,
"srcb" :result,
"element_size" :self.lvalue.declaration.element_size})
self.allocator.free(index)
self.allocator.free(address)
Expression.__init__(
self,
function.type_,
function.size,
function.signed)
 
return instructions
def generate(self, result, allocator):
instructions = []
 
class Constant:
def __init__(self, value, size=2, signed=True):
self._value = value
self.type_ = "int"
self.size = size
self.signed = signed
for expression, argument in zip(
self.arguments,
self.function.arguments):
 
def generate(self, result):
instructions = [{"op":"literal", "dest":result, "literal":self._value}]
return instructions
temp_register = allocator.new(expression.size())
instructions.extend(
argument.copy(expression, temp_register, allocator))
allocator.free(temp_register)
 
def value(self):
return self._value
instructions.append(
{"op" :"jmp_and_link",
"dest" :self.function.return_address,
"label":"function_%s"%id(self.function)})
 
if hasattr(self.function, "return_value"):
 
instructions.extend(self.function.return_value.generate(
result,
allocator))
 
return instructions
 
 
class Output(Expression):
 
def __init__(self, name, expression):
self.name = name
self.expression = expression
Expression.__init__(self, "int", 2, True)
 
def generate(self, result, allocator):
instructions = self.expression.generate(result, allocator)
 
instructions.append(
{"op" :"write",
"src" :result,
"output":self.name})
 
return instructions
 
 
class FileWrite(Expression):
 
def __init__(self, name, expression):
self.name = name
self.expression = expression
Expression.__init__(
self,
expression.type_(),
expression.size(),
expression.signed())
 
def generate(self, result, allocator):
instructions = self.expression.generate(result, allocator)
 
instructions.append(
{"op" :"file_write",
"src" :result,
"type":self.expression.type_(),
"file_name":self.name})
 
return instructions
 
 
class Input(Expression):
 
def __init__(self, name):
self.name = name
Expression.__init__(self, "int", 2, True)
 
def generate(self, result, allocator):
return [{"op" :"read", "dest" :result, "input":self.name}]
 
 
class FileRead(Expression):
 
def __init__(self, name):
self.name = name
Expression.__init__(self, "int", 2, True)
 
def generate(self, result, allocator):
return [{"op" :"file_read", "dest" :result, "file_name":self.name}]
 
 
class Ready(Expression):
 
def __init__(self, name):
self.name = name
Expression.__init__(self, "int", 2, True)
 
def generate(self, result, allocator):
return [{"op" :"ready", "dest" :result, "input":self.name}]
 
 
class Struct(Object):
 
def __init__(self, instance):
Object.__init__(self, instance)
 
def generate(self, result, allocator):
instructions = []
if result != self.declaration.register:
 
instructions.append(
{"op" :"move",
"dest":result,
"src" :self.declaration.register})
 
return instructions
 
def copy(self, expression, result, allocator):
instructions = []
 
for lvalue, rvalue in zip(
self.instance.members.values(),
expression.instance.members.values()):
 
instructions.extend(
lvalue.reference().copy(rvalue.reference(), result, allocator))
 
return instructions
 
 
class Array(Object):
 
def __init__(self, instance):
Object.__init__(self, instance)
 
def generate(self, result, allocator):
instructions = []
if result != self.instance.register:
 
instructions.append(
{"op" : "move",
"dest" : result,
"src" : self.instance.register})
 
return instructions
 
def copy(self, expression, result, allocator):
instructions = expression.generate(result, allocator)
if result != self.instance.register:
 
instructions.append(
{"op" : "move",
"dest" : self.instance.register,
"src" : result})
 
return instructions
 
 
class ConstArray(Object):
 
def __init__(self, instance):
Object.__init__(self, instance)
 
def generate(self, result, allocator):
instructions = []
#If initialize memory is true, the memory content will initialised (as at configuration time)
#If initialize memory is false, then the memory will need to be filled by the program.
if not self.instance.initialize_memory and self.instance.initializer is not None:
location = self.instance.location
for value in self.instance.initializer:
 
instructions.append(
{"op":"memory_write_literal",
"address":location,
"value":value,
"element_size":self.instance.element_size})
 
location += 1
 
instructions.append(
{"op":"literal",
"literal":self.instance.location,
"dest":self.instance.register})
 
if result != self.instance.register:
 
instructions.append(
{"op" : "move",
"dest" : result,
"src" : self.instance.register})
 
return instructions
 
def copy(self, expression, result, allocator):
instructions = expression.generate(result, allocator)
if result != self.instance.register:
 
instructions.append(
{"op" : "move",
"dest" : self.instance.register,
"src" : result})
 
return instructions
 
 
class ArrayIndex(Object):
 
def __init__(self, instance, index_expression):
Object.__init__(self, instance)
assert self.type_var.endswith("[]")
self.type_var = self.type_var[:-2]
self.size_var = instance.element_size
self.index_expression = index_expression
 
def generate(self, result, allocator):
instructions = []
offset = allocator.new(2)
address = allocator.new(2)
instructions.extend(self.index_expression.generate(offset, allocator))
 
instructions.append(
{"op" :"+",
"dest" :address,
"src" :offset,
"srcb" :self.instance.register,
"signed":False})
 
instructions.append(
{"op" :"memory_read_request",
"src" :address,
"sequence": id(self),
"element_size":self.size()})
 
instructions.append(
{"op" :"memory_read_wait",
"src" :address,
"sequence": id(self),
"element_size":self.size()})
 
instructions.append(
{"op" :"memory_read",
"src" :address,
"dest" :result,
"sequence": id(self),
"element_size":self.size()})
 
allocator.free(address)
allocator.free(offset)
return instructions
 
def copy(self, expression, result, allocator):
index = allocator.new(2)
address = allocator.new(2)
instructions = expression.generate(result, allocator)
instructions.extend(self.index_expression.generate(index, allocator))
 
instructions.append(
{"op" :"+",
"dest" :address,
"src" :index,
"srcb" :self.instance.register,
"signed" :expression.signed()})
 
instructions.append(
{"op" :"memory_write",
"src" :address,
"srcb" :result,
"element_size" :self.instance.element_size})
 
allocator.free(index)
allocator.free(address)
return instructions
 
 
class Variable(Object):
def __init__(self, instance):
Object.__init__(self, instance)
 
def generate(self, result, allocator):
instructions = []
if result != self.instance.register:
 
instructions.append(
{"op" :"move",
"dest":result,
"src" :self.instance.register})
 
return instructions
 
def copy(self, expression, result, allocator):
instructions = expression.generate(result, allocator)
if result != self.instance.register:
 
instructions.append(
{"op" : "move",
"dest" : self.instance.register,
"src" : result})
 
return instructions
 
def const(self):
return self.instance.const()
 
def value(self):
if self.const():
return self.instance.initializer.value()
else:
raise NotConstant
 
 
class PostIncrement(Expression):
 
def __init__(self, operator, lvalue, allocator):
self.operator = operator
self.lvalue = lvalue
allocator = allocator
Expression.__init__(self, lvalue.type_(), lvalue.size(), lvalue.signed())
 
def generate(self, result, allocator):
 
instructions = []
 
instructions.append(
{"op" : "move",
"src" : self.lvalue.instance.register,
"dest" : result})
 
instructions.append(
{"op" : self.operator,
"dest" : self.lvalue.instance.register,
"right" : 1,
"src" : self.lvalue.instance.register,
"size" : self.size(),
"signed": self.signed()})
 
return instructions
 
 
class Assignment(Expression):
 
def __init__(self, lvalue, expression, allocator):
Expression.__init__(self, lvalue.type_(), lvalue.size(), lvalue.signed())
self.lvalue = lvalue
self.expression = expression
self.allocator = allocator
 
def generate(self, result, allocator):
return self.lvalue.copy(self.expression, result, allocator)
 
 
class Constant(Expression):
 
def __init__(self, value, type_="int", size=2, signed=True):
self._value = value
Expression.__init__(self, type_, size, signed)
 
def generate(self, result, allocator):
 
instructions = [{
"op":"literal",
"dest":result,
"size":self.size(),
"signed":self.size(),
"literal":self.int_value()}]
return instructions
 
def value(self):
return self._value
 
 
/chips/compiler/compiler.py
19,66 → 19,66
 
def comp(input_file, options=[]):
 
reuse = "no_reuse" not in options
initialize_memory = "no_initialize_memory" not in options
reuse = "no_reuse" not in options
initialize_memory = "no_initialize_memory" not in options
 
try:
if "speed" not in options:
try:
if "speed" not in options:
 
#Optimize for area
parser = Parser(input_file, reuse, initialize_memory)
process = parser.parse_process()
name = process.main.name
instructions = process.generate()
instructions = cleanup_functions(instructions)
instructions, registers = cleanup_registers(instructions, parser.allocator.all_registers)
output_file = name + ".v"
output_file = open(output_file, "w")
inputs, outputs = generate_CHIP_area(
input_file,
name,
instructions,
output_file,
registers,
parser.allocator.memory_size_2,
parser.allocator.memory_size_4,
initialize_memory,
parser.allocator.memory_content_2,
parser.allocator.memory_content_4)
output_file.close()
#Optimize for area
parser = Parser(input_file, reuse, initialize_memory)
process = parser.parse_process()
name = process.main.name
instructions = process.generate()
instructions = cleanup_functions(instructions)
instructions, registers = cleanup_registers(instructions, parser.allocator.all_registers)
output_file = name + ".v"
output_file = open(output_file, "w")
inputs, outputs = generate_CHIP_area(
input_file,
name,
instructions,
output_file,
registers,
parser.allocator.memory_size_2,
parser.allocator.memory_size_4,
initialize_memory,
parser.allocator.memory_content_2,
parser.allocator.memory_content_4)
output_file.close()
 
else:
else:
 
#Optimize for speed
parser = Parser(input_file, reuse, initialize_memory)
process = parser.parse_process()
name = process.main.name
instructions = process.generate()
instructions = cleanup_functions(instructions)
instructions, registers = cleanup_registers(instructions, parser.allocator.all_registers)
if "no_concurrent" in sys.argv:
frames = [[i] for i in instructions]
else:
frames = parallelise(instructions)
output_file = name + ".v"
output_file = open(output_file, "w")
inputs, outputs = generate_CHIP_speed(
input_file,
name,
frames,
output_file,
registers,
parser.allocator.memory_size_2,
parser.allocator.memory_size_4,
initialize_memory,
parser.allocator.memory_content_2,
parser.allocator.memory_content_4)
output_file.close()
#Optimize for speed
parser = Parser(input_file, reuse, initialize_memory)
process = parser.parse_process()
name = process.main.name
instructions = process.generate()
instructions = cleanup_functions(instructions)
instructions, registers = cleanup_registers(instructions, parser.allocator.all_registers)
if "no_concurrent" in sys.argv:
frames = [[i] for i in instructions]
else:
frames = parallelise(instructions)
output_file = name + ".v"
output_file = open(output_file, "w")
inputs, outputs = generate_CHIP_speed(
input_file,
name,
frames,
output_file,
registers,
parser.allocator.memory_size_2,
parser.allocator.memory_size_4,
initialize_memory,
parser.allocator.memory_content_2,
parser.allocator.memory_content_4)
output_file.close()
 
except C2CHIPError as err:
print "Error in file:", err.filename, "at line:", err.lineno
print err.message
sys.exit(-1)
except C2CHIPError as err:
print "Error in file:", err.filename, "at line:", err.lineno
print err.message
sys.exit(-1)
 
 
return name, inputs, outputs, ""
return name, inputs, outputs, ""
/chips/compiler/fpu.py
0,0 → 1,1130
divider = """//IEEE Floating Point Divider (Single Precision)
//Copyright (C) Jonathan P Dawson 2013
//2013-12-12
//
module divider(
input_a,
input_b,
input_a_stb,
input_b_stb,
output_z_ack,
clk,
rst,
output_z,
output_z_stb,
input_a_ack,
input_b_ack);
 
input clk;
input rst;
 
input [31:0] input_a;
input input_a_stb;
output input_a_ack;
 
input [31:0] input_b;
input input_b_stb;
output input_b_ack;
 
output [31:0] output_z;
output output_z_stb;
input output_z_ack;
 
reg s_output_z_stb;
reg [31:0] s_output_z;
reg s_input_a_ack;
reg s_input_b_ack;
 
reg [3:0] state;
parameter get_a = 4'd0,
get_b = 4'd1,
unpack = 4'd2,
special_cases = 4'd3,
normalise_a = 4'd4,
normalise_b = 4'd5,
divide_0 = 4'd6,
divide_1 = 4'd7,
divide_2 = 4'd8,
divide_3 = 4'd9,
normalise_1 = 4'd10,
normalise_2 = 4'd11,
round = 4'd12,
pack = 4'd13,
put_z = 4'd14;
 
reg [31:0] a, b, z;
reg [23:0] a_m, b_m, z_m;
reg [9:0] a_e, b_e, z_e;
reg a_s, b_s, z_s;
reg guard, round_bit, sticky;
reg [50:0] quotient, divisor, dividend, remainder;
reg [5:0] count;
 
always @(posedge clk)
begin
 
case(state)
 
get_a:
begin
s_input_a_ack <= 1;
if (s_input_a_ack && input_a_stb) begin
a <= input_a;
s_input_a_ack <= 0;
state <= get_b;
end
end
 
get_b:
begin
s_input_b_ack <= 1;
if (s_input_b_ack && input_b_stb) begin
b <= input_b;
s_input_b_ack <= 0;
state <= unpack;
end
end
 
unpack:
begin
a_m <= a[22 : 0];
b_m <= b[22 : 0];
a_e <= a[30 : 23] - 127;
b_e <= b[30 : 23] - 127;
a_s <= a[31];
b_s <= b[31];
state <= special_cases;
end
 
special_cases:
begin
//if a is NaN or b is NaN return NaN
if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
//if a is inf and b is inf return NaN
end else if ((a_e == 128) && (b_e == 128)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
//if a is inf return inf
end else if (a_e == 128) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 255;
z[22:0] <= 0;
state <= put_z;
//if b is zero return NaN
if ($signed(b_e == -127) && (b_m == 0)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
end
//if b is inf return zero
end else if (b_e == 128) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 0;
z[22:0] <= 0;
state <= put_z;
//if a is zero return zero
end else if (($signed(a_e) == -127) && (a_m == 0)) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 0;
z[22:0] <= 0;
state <= put_z;
//if b is zero return NaN
if (($signed(b_e) == -127) && (b_m == 0)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
end
//if b is zero return inf
end else if (($signed(b_e) == -127) && (b_m == 0)) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 255;
z[22:0] <= 0;
state <= put_z;
end else begin
//Denormalised Number
if ($signed(a_e) == -127) begin
a_e <= -126;
end else begin
a_m[23] <= 1;
end
//Denormalised Number
if ($signed(b_e) == -127) begin
b_e <= -126;
end else begin
b_m[23] <= 1;
end
state <= normalise_a;
end
end
 
normalise_a:
begin
if (a_m[23]) begin
state <= normalise_b;
end else begin
a_m <= a_m << 1;
a_e <= a_e - 1;
end
end
 
normalise_b:
begin
if (b_m[23]) begin
state <= divide_0;
end else begin
b_m <= b_m << 1;
b_e <= b_e - 1;
end
end
 
divide_0:
begin
z_s <= a_s ^ b_s;
z_e <= a_e - b_e;
quotient <= 0;
remainder <= 0;
count <= 0;
dividend <= a_m << 27;
divisor <= b_m;
state <= divide_1;
end
 
divide_1:
begin
quotient <= quotient << 1;
remainder <= remainder << 1;
remainder[0] <= dividend[50];
dividend <= dividend << 1;
state <= divide_2;
end
 
divide_2:
begin
if (remainder >= divisor) begin
quotient[0] <= 1;
remainder <= remainder - divisor;
end
if (count == 49) begin
state <= divide_3;
end else begin
count <= count + 1;
state <= divide_1;
end
end
 
divide_3:
begin
z_m <= quotient[26:3];
guard <= quotient[2];
round_bit <= quotient[1];
sticky <= quotient[0] | (remainder != 0);
state <= normalise_1;
end
 
normalise_1:
begin
if (z_m[23] == 0 && $signed(z_e) > -126) begin
z_e <= z_e - 1;
z_m <= z_m << 1;
z_m[0] <= guard;
guard <= round_bit;
round_bit <= 0;
end else begin
state <= normalise_2;
end
end
 
normalise_2:
begin
if ($signed(z_e) < -126) begin
z_e <= z_e + 1;
z_m <= z_m >> 1;
guard <= z_m[0];
round_bit <= guard;
sticky <= sticky | round_bit;
end else begin
state <= round;
end
end
 
round:
begin
if (guard && (round_bit | sticky | z_m[0])) begin
z_m <= z_m + 1;
if (z_m == 24'hffffff) begin
z_e <=z_e + 1;
end
end
state <= pack;
end
 
pack:
begin
z[22 : 0] <= z_m[22:0];
z[30 : 23] <= z_e[7:0] + 127;
z[31] <= z_s;
if ($signed(z_e) == -126 && z_m[23] == 0) begin
z[30 : 23] <= 0;
end
//if overflow occurs, return inf
if ($signed(z_e) > 127) begin
z[22 : 0] <= 0;
z[30 : 23] <= 255;
z[31] <= z_s;
end
state <= put_z;
end
 
put_z:
begin
s_output_z_stb <= 1;
s_output_z <= z;
if (s_output_z_stb && output_z_ack) begin
s_output_z_stb <= 0;
state <= get_a;
end
end
 
endcase
 
if (rst == 1) begin
state <= get_a;
s_input_a_ack <= 0;
s_input_b_ack <= 0;
s_output_z_stb <= 0;
end
 
end
assign input_a_ack = s_input_a_ack;
assign input_b_ack = s_input_b_ack;
assign output_z_stb = s_output_z_stb;
assign output_z = s_output_z;
 
endmodule
 
"""
multiplier = """//IEEE Floating Point Multiplier (Single Precision)
//Copyright (C) Jonathan P Dawson 2013
//2013-12-12
module multiplier(
input_a,
input_b,
input_a_stb,
input_b_stb,
output_z_ack,
clk,
rst,
output_z,
output_z_stb,
input_a_ack,
input_b_ack);
 
input clk;
input rst;
 
input [31:0] input_a;
input input_a_stb;
output input_a_ack;
 
input [31:0] input_b;
input input_b_stb;
output input_b_ack;
 
output [31:0] output_z;
output output_z_stb;
input output_z_ack;
 
reg s_output_z_stb;
reg [31:0] s_output_z;
reg s_input_a_ack;
reg s_input_b_ack;
 
reg [3:0] state;
parameter get_a = 4'd0,
get_b = 4'd1,
unpack = 4'd2,
special_cases = 4'd3,
normalise_a = 4'd4,
normalise_b = 4'd5,
multiply_0 = 4'd6,
multiply_1 = 4'd7,
normalise_1 = 4'd8,
normalise_2 = 4'd9,
round = 4'd10,
pack = 4'd11,
put_z = 4'd12;
 
reg [31:0] a, b, z;
reg [23:0] a_m, b_m, z_m;
reg [9:0] a_e, b_e, z_e;
reg a_s, b_s, z_s;
reg guard, round_bit, sticky;
reg [49:0] product;
 
always @(posedge clk)
begin
 
case(state)
 
get_a:
begin
s_input_a_ack <= 1;
if (s_input_a_ack && input_a_stb) begin
a <= input_a;
s_input_a_ack <= 0;
state <= get_b;
end
end
 
get_b:
begin
s_input_b_ack <= 1;
if (s_input_b_ack && input_b_stb) begin
b <= input_b;
s_input_b_ack <= 0;
state <= unpack;
end
end
 
unpack:
begin
a_m <= a[22 : 0];
b_m <= b[22 : 0];
a_e <= a[30 : 23] - 127;
b_e <= b[30 : 23] - 127;
a_s <= a[31];
b_s <= b[31];
state <= special_cases;
end
 
special_cases:
begin
//if a is NaN or b is NaN return NaN
if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
//if a is inf return inf
end else if (a_e == 128) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 255;
z[22:0] <= 0;
state <= put_z;
//if b is zero return NaN
if ($signed(b_e == -127) && (b_m == 0)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
end
//if b is inf return inf
end else if (b_e == 128) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 255;
z[22:0] <= 0;
state <= put_z;
//if a is zero return zero
end else if (($signed(a_e) == -127) && (a_m == 0)) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 0;
z[22:0] <= 0;
state <= put_z;
//if b is zero return zero
end else if (($signed(b_e) == -127) && (b_m == 0)) begin
z[31] <= a_s ^ b_s;
z[30:23] <= 0;
z[22:0] <= 0;
state <= put_z;
end else begin
//Denormalised Number
if ($signed(a_e) == -127) begin
a_e <= -126;
end else begin
a_m[23] <= 1;
end
//Denormalised Number
if ($signed(b_e) == -127) begin
b_e <= -126;
end else begin
b_m[23] <= 1;
end
state <= normalise_a;
end
end
 
normalise_a:
begin
if (a_m[23]) begin
state <= normalise_b;
end else begin
a_m <= a_m << 1;
a_e <= a_e - 1;
end
end
 
normalise_b:
begin
if (b_m[23]) begin
state <= multiply_0;
end else begin
b_m <= b_m << 1;
b_e <= b_e - 1;
end
end
 
multiply_0:
begin
z_s <= a_s ^ b_s;
z_e <= a_e + b_e + 1;
product <= a_m * b_m * 4;
state <= multiply_1;
end
 
multiply_1:
begin
z_m <= product[49:26];
guard <= product[25];
round_bit <= product[24];
sticky <= (product[23:0] != 0);
state <= normalise_1;
end
 
normalise_1:
begin
if (z_m[23] == 0) begin
z_e <= z_e - 1;
z_m <= z_m << 1;
z_m[0] <= guard;
guard <= round_bit;
round_bit <= 0;
end else begin
state <= normalise_2;
end
end
 
normalise_2:
begin
if ($signed(z_e) < -126) begin
z_e <= z_e + 1;
z_m <= z_m >> 1;
guard <= z_m[0];
round_bit <= guard;
sticky <= sticky | round_bit;
end else begin
state <= round;
end
end
 
round:
begin
if (guard && (round_bit | sticky | z_m[0])) begin
z_m <= z_m + 1;
if (z_m == 24'hffffff) begin
z_e <=z_e + 1;
end
end
state <= pack;
end
 
pack:
begin
z[22 : 0] <= z_m[22:0];
z[30 : 23] <= z_e[7:0] + 127;
z[31] <= z_s;
if ($signed(z_e) == -126 && z_m[23] == 0) begin
z[30 : 23] <= 0;
end
//if overflow occurs, return inf
if ($signed(z_e) > 127) begin
z[22 : 0] <= 0;
z[30 : 23] <= 255;
z[31] <= z_s;
end
state <= put_z;
end
 
put_z:
begin
s_output_z_stb <= 1;
s_output_z <= z;
if (s_output_z_stb && output_z_ack) begin
s_output_z_stb <= 0;
state <= get_a;
end
end
 
endcase
 
if (rst == 1) begin
state <= get_a;
s_input_a_ack <= 0;
s_input_b_ack <= 0;
s_output_z_stb <= 0;
end
 
end
assign input_a_ack = s_input_a_ack;
assign input_b_ack = s_input_b_ack;
assign output_z_stb = s_output_z_stb;
assign output_z = s_output_z;
 
endmodule
 
"""
adder = """//IEEE Floating Point Adder (Single Precision)
//Copyright (C) Jonathan P Dawson 2013
//2013-12-12
 
module adder(
input_a,
input_b,
input_a_stb,
input_b_stb,
output_z_ack,
clk,
rst,
output_z,
output_z_stb,
input_a_ack,
input_b_ack);
 
input clk;
input rst;
 
input [31:0] input_a;
input input_a_stb;
output input_a_ack;
 
input [31:0] input_b;
input input_b_stb;
output input_b_ack;
 
output [31:0] output_z;
output output_z_stb;
input output_z_ack;
 
reg s_output_z_stb;
reg [31:0] s_output_z;
reg s_input_a_ack;
reg s_input_b_ack;
 
reg [3:0] state;
parameter get_a = 4'd0,
get_b = 4'd1,
unpack = 4'd2,
special_cases = 4'd3,
align = 4'd4,
add_0 = 4'd5,
add_1 = 4'd6,
normalise_1 = 4'd7,
normalise_2 = 4'd8,
round = 4'd9,
pack = 4'd10,
put_z = 4'd11;
 
reg [31:0] a, b, z;
reg [26:0] a_m, b_m;
reg [23:0] z_m;
reg [9:0] a_e, b_e, z_e;
reg a_s, b_s, z_s;
reg guard, round_bit, sticky;
reg [27:0] sum;
 
always @(posedge clk)
begin
 
case(state)
 
get_a:
begin
s_input_a_ack <= 1;
if (s_input_a_ack && input_a_stb) begin
a <= input_a;
s_input_a_ack <= 0;
state <= get_b;
end
end
 
get_b:
begin
s_input_b_ack <= 1;
if (s_input_b_ack && input_b_stb) begin
b <= input_b;
s_input_b_ack <= 0;
state <= unpack;
end
end
 
unpack:
begin
a_m <= {a[22 : 0], 3'd0};
b_m <= {b[22 : 0], 3'd0};
a_e <= a[30 : 23] - 127;
b_e <= b[30 : 23] - 127;
a_s <= a[31];
b_s <= b[31];
state <= special_cases;
end
 
special_cases:
begin
//if a is NaN or b is NaN return NaN
if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
z[31] <= 1;
z[30:23] <= 255;
z[22] <= 1;
z[21:0] <= 0;
state <= put_z;
//if a is inf return inf
end else if (a_e == 128) begin
z[31] <= a_s;
z[30:23] <= 255;
z[22:0] <= 0;
state <= put_z;
//if b is inf return inf
end else if (b_e == 128) begin
z[31] <= b_s;
z[30:23] <= 255;
z[22:0] <= 0;
state <= put_z;
//if a is zero return b
end else if ((($signed(a_e) == -127) && (a_m == 0)) && (($signed(b_e) == -127) && (b_m == 0))) begin
z[31] <= a_s & b_s;
z[30:23] <= b_e[7:0] + 127;
z[22:0] <= b_m[26:3];
state <= put_z;
//if a is zero return b
end else if (($signed(a_e) == -127) && (a_m == 0)) begin
z[31] <= b_s;
z[30:23] <= b_e[7:0] + 127;
z[22:0] <= b_m[26:3];
state <= put_z;
//if b is zero return a
end else if (($signed(b_e) == -127) && (b_m == 0)) begin
z[31] <= a_s;
z[30:23] <= a_e[7:0] + 127;
z[22:0] <= a_m[26:3];
state <= put_z;
end else begin
//Denormalised Number
if ($signed(a_e) == -127) begin
a_e <= -126;
end else begin
a_m[26] <= 1;
end
//Denormalised Number
if ($signed(b_e) == -127) begin
b_e <= -126;
end else begin
b_m[26] <= 1;
end
state <= align;
end
end
 
align:
begin
if ($signed(a_e) > $signed(b_e)) begin
b_e <= b_e + 1;
b_m <= b_m >> 1;
b_m[0] <= b_m[0] | b_m[1];
end else if ($signed(a_e) < $signed(b_e)) begin
a_e <= a_e + 1;
a_m <= a_m >> 1;
a_m[0] <= a_m[0] | a_m[1];
end else begin
state <= add_0;
end
end
 
add_0:
begin
z_e <= a_e;
if (a_s == b_s) begin
sum <= a_m + b_m;
z_s <= a_s;
end else begin
if (a_m >= b_m) begin
sum <= a_m - b_m;
z_s <= a_s;
end else begin
sum <= b_m - a_m;
z_s <= b_s;
end
end
state <= add_1;
end
 
add_1:
begin
if (sum[27]) begin
z_m <= sum[27:4];
guard <= sum[3];
round_bit <= sum[2];
sticky <= sum[1] | sum[0];
z_e <= z_e + 1;
end else begin
z_m <= sum[26:3];
guard <= sum[2];
round_bit <= sum[1];
sticky <= sum[0];
end
state <= normalise_1;
end
 
normalise_1:
begin
if (z_m[23] == 0 && $signed(z_e) > -126) begin
z_e <= z_e - 1;
z_m <= z_m << 1;
z_m[0] <= guard;
guard <= round_bit;
round_bit <= 0;
end else begin
state <= normalise_2;
end
end
 
normalise_2:
begin
if ($signed(z_e) < -126) begin
z_e <= z_e + 1;
z_m <= z_m >> 1;
guard <= z_m[0];
round_bit <= guard;
sticky <= sticky | round_bit;
end else begin
state <= round;
end
end
 
round:
begin
if (guard && (round_bit | sticky | z_m[0])) begin
z_m <= z_m + 1;
if (z_m == 24'hffffff) begin
z_e <=z_e + 1;
end
end
state <= pack;
end
 
pack:
begin
z[22 : 0] <= z_m[22:0];
z[30 : 23] <= z_e[7:0] + 127;
z[31] <= z_s;
if ($signed(z_e) == -126 && z_m[23] == 0) begin
z[30 : 23] <= 0;
end
//if overflow occurs, return inf
if ($signed(z_e) > 127) begin
z[22 : 0] <= 0;
z[30 : 23] <= 255;
z[31] <= z_s;
end
state <= put_z;
end
 
put_z:
begin
s_output_z_stb <= 1;
s_output_z <= z;
if (s_output_z_stb && output_z_ack) begin
s_output_z_stb <= 0;
state <= get_a;
end
end
 
endcase
 
if (rst == 1) begin
state <= get_a;
s_input_a_ack <= 0;
s_input_b_ack <= 0;
s_output_z_stb <= 0;
end
 
end
assign input_a_ack = s_input_a_ack;
assign input_b_ack = s_input_b_ack;
assign output_z_stb = s_output_z_stb;
assign output_z = s_output_z;
 
endmodule
 
"""
int_to_float = """//Integer to IEEE Floating Point Converter (Single Precision)
//Copyright (C) Jonathan P Dawson 2013
//2013-12-12
module int_to_float(
input_a,
input_a_stb,
output_z_ack,
clk,
rst,
output_z,
output_z_stb,
input_a_ack);
 
input clk;
input rst;
 
input [31:0] input_a;
input input_a_stb;
output input_a_ack;
 
output [31:0] output_z;
output output_z_stb;
input output_z_ack;
 
reg s_output_z_stb;
reg [31:0] s_output_z;
reg s_input_a_ack;
reg s_input_b_ack;
 
reg [2:0] state;
parameter get_a = 3'd0,
convert_0 = 3'd1,
convert_1 = 3'd2,
convert_2 = 3'd3,
round = 3'd4,
pack = 3'd5,
put_z = 3'd6;
 
reg [31:0] a, z, value;
reg [23:0] z_m;
reg [7:0] z_r;
reg [7:0] z_e;
reg z_s;
reg guard, round_bit, sticky;
 
always @(posedge clk)
begin
 
case(state)
 
get_a:
begin
s_input_a_ack <= 1;
if (s_input_a_ack && input_a_stb) begin
a <= input_a;
s_input_a_ack <= 0;
state <= convert_0;
end
end
 
convert_0:
begin
if ( a == 0 ) begin
z_s <= 0;
z_m <= 0;
z_e <= -127;
state <= pack;
end else begin
value <= a[31] ? -a : a;
z_s <= a[31];
state <= convert_1;
end
end
 
convert_1:
begin
z_e <= 31;
z_m <= value[31:8];
z_r <= value[7:0];
state <= convert_2;
end
 
convert_2:
begin
if (!z_m[23]) begin
z_e <= z_e - 1;
z_m <= z_m << 1;
z_m[0] <= z_r[7];
z_r <= z_r << 1;
end else begin
guard <= z_r[7];
round_bit <= z_r[6];
sticky <= z_r[5:0] != 0;
state <= round;
end
end
 
round:
begin
if (guard && (round_bit || sticky || z_m[0])) begin
z_m <= z_m + 1;
if (z_m == 24'hffffff) begin
z_e <=z_e + 1;
end
end
state <= pack;
end
 
pack:
begin
z[22 : 0] <= z_m[22:0];
z[30 : 23] <= z_e + 127;
z[31] <= z_s;
state <= put_z;
end
 
put_z:
begin
s_output_z_stb <= 1;
s_output_z <= z;
if (s_output_z_stb && output_z_ack) begin
s_output_z_stb <= 0;
state <= get_a;
end
end
 
endcase
 
if (rst == 1) begin
state <= get_a;
s_input_a_ack <= 0;
s_output_z_stb <= 0;
end
 
end
assign input_a_ack = s_input_a_ack;
assign output_z_stb = s_output_z_stb;
assign output_z = s_output_z;
 
endmodule
 
"""
float_to_int = """//IEEE Floating Point to Integer Converter (Single Precision)
//Copyright (C) Jonathan P Dawson 2013
//2013-12-12
module float_to_int(
input_a,
input_a_stb,
output_z_ack,
clk,
rst,
output_z,
output_z_stb,
input_a_ack);
 
input clk;
input rst;
 
input [31:0] input_a;
input input_a_stb;
output input_a_ack;
 
output [31:0] output_z;
output output_z_stb;
input output_z_ack;
 
reg s_output_z_stb;
reg [31:0] s_output_z;
reg s_input_a_ack;
 
reg [2:0] state;
parameter get_a = 3'd0,
special_cases = 3'd1,
unpack = 3'd2,
convert = 3'd3,
put_z = 3'd4;
 
reg [31:0] a_m, a, z;
reg [8:0] a_e;
reg a_s;
 
always @(posedge clk)
begin
 
case(state)
 
get_a:
begin
s_input_a_ack <= 1;
if (s_input_a_ack && input_a_stb) begin
a <= input_a;
s_input_a_ack <= 0;
state <= unpack;
end
end
 
unpack:
begin
a_m[31:8] <= {1'b1, a[22 : 0]};
a_m[7:0] <= 0;
a_e <= a[30 : 23] - 127;
a_s <= a[31];
state <= special_cases;
end
 
special_cases:
begin
if ($signed(a_e) == -127) begin
z <= 0;
state <= put_z;
end else if ($signed(a_e) > 31) begin
z <= 32'h80000000;
state <= put_z;
end else begin
state <= convert;
end
end
 
convert:
begin
if ($signed(a_e) < 31) begin
a_e <= a_e + 1;
a_m <= a_m >> 1;
end else begin
if (a_m[31]) begin
z <= 32'h80000000;
end else begin
z <= a_s ? -a_m : a_m;
end
state <= put_z;
end
end
 
put_z:
begin
s_output_z_stb <= 1;
s_output_z <= z;
if (s_output_z_stb && output_z_ack) begin
s_output_z_stb <= 0;
state <= get_a;
end
end
 
endcase
 
if (rst == 1) begin
state <= get_a;
s_input_a_ack <= 0;
s_output_z_stb <= 0;
end
 
end
assign input_a_ack = s_input_a_ack;
assign output_z_stb = s_output_z_stb;
assign output_z = s_output_z;
 
endmodule
 
"""
/chips/compiler/parser.py
2,10 → 2,17
__copyright__ = "Copyright (C) 2012, Jonathan P Dawson"
__version__ = "0.1"
 
import struct
from copy import copy
 
from parse_tree import *
from tokens import Tokens
from allocator import Allocator
 
types = ["float", "signed", "unsigned", "short", "long", "char", "int", "void"]
numeric_types = ["float", "signed", "unsigned", "short", "long", "char", "int"]
storage_specifiers = ["const"]
 
class Parser:
 
"""Turn the C input file into a tree of expressions and statements."""
38,7 → 45,7
def parse_type_specifier(self):
type_specifiers = []
 
while self.tokens.peek() in ["signed", "unsigned", "short", "long", "char", "int", "void"] + self.structs:
while self.tokens.peek() in types + self.structs + storage_specifiers:
type_specifiers.append(self.tokens.get())
 
signed = True
60,6 → 67,21
size = 2
signed = False
 
if "float" in type_specifiers:
if "short" in type_specifiers:
self.tokens.error("Float cannot be short")
if "long" in type_specifiers:
self.tokens.error("Float cannot be long (but double can)")
if "unsigned" in type_specifiers:
self.tokens.error("Float cannot be unsigned")
type_ = "float"
size = 4
signed = True
 
const = False
if "const" in type_specifiers:
const = True
 
if "void" in type_specifiers:
type_ = "void"
size = 2
66,18 → 88,53
signed = False
 
 
return type_, size, signed
return type_, size, signed, const
 
def parse_argument(self):
type_, size, signed, const = self.parse_type_specifier()
 
if type_ in ["void"]:
self.tokens.error("argument cannot be void")
else:
argument = self.tokens.get()
if type_ in self.structs:
declaration = self.scope[type_]
else:
if self.tokens.peek() == "[":
self.tokens.expect("[")
self.tokens.expect("]")
declaration = ArrayDeclaration(
self.allocator,
2,
type_+"[]",
type_,
size,
signed,
None,
self.initialize_memory)
else:
declaration = VariableDeclaration(
self.allocator,
None,
argument,
type_,
size,
signed,
const)
instance = declaration.instance()
self.scope[argument] = instance
return instance.reference()
 
def parse_function(self):
function = Function()
function.allocator = self.allocator
stored_scope = self.scope
type_, size, signed = self.parse_type_specifier()
stored_scope = copy(self.scope)
type_, size, signed, const = self.parse_type_specifier()
name = self.tokens.get()
 
#check if it is a global declaration
if self.tokens.peek() != "(":
return self.parse_global_declaration(type_, size, signed, name)
return self.parse_global_declaration(type_, size, signed, const, name)
 
#otherwise continue parsing a function
self.tokens.expect("(")
85,41 → 142,38
function.type_ = type_
function.size = size
function.signed = signed
function.return_address = self.allocator.new(2, function.name+" return address")
 
function.return_address = self.allocator.new(2,
function.name+" return address")
 
if type_ != "void":
function.return_value = self.allocator.new(function.size, function.name+" return value")
 
if type_ in self.structs:
declaration = self.scope[type_]
else:
if self.tokens.peek() == "[":
self.tokens.error(
"Functions cannot return arrays")
else:
declaration = VariableDeclaration(
self.allocator,
None,
function.name+" return value",
type_,
size,
signed,
const)
 
function.return_value = declaration.instance().reference()
 
function.arguments = []
while self.tokens.peek() != ")":
argument_type, argument_size, argument_signed = self.parse_type_specifier()
if argument_type in ["void"]:
self.tokens.error("argument cannot be void")
argument = self.tokens.get()
element_type = None
element_size = None
element_signed = None
if self.tokens.peek() == "[":
self.tokens.expect("[")
self.tokens.expect("]")
element_type = argument_type
element_size = argument_size
element_signed = argument_signed
argument_type+="[]"
argument_size = 2
argument_signed = False
 
function.arguments.append(Argument(
argument,
argument_type,
argument_size,
argument_signed,
self,
element_type,
element_size,
element_signed))
function.arguments.append(self.parse_argument())
if self.tokens.peek() == ",":
self.tokens.expect(",")
else:
break
 
self.tokens.expect(")")
self.function = function
function.statement = self.parse_statement()
149,6 → 203,7
def parse_return(self):
return_ = Return()
return_.function = self.function
return_.allocator = self.allocator
self.function.return_statement = return_
self.tokens.expect("return")
if hasattr(self.function, "return_value"):
192,7 → 247,7
return wait_clocks
 
def parse_statement(self):
if self.tokens.peek() in ["unsigned", "int", "short", "long", "char"] + self.structs:
if self.tokens.peek() in numeric_types + self.structs + storage_specifiers:
return self.parse_compound_declaration()
elif self.tokens.peek() == "struct":
return self.parse_struct_declaration()
232,28 → 287,36
 
def parse_assignment(self):
assignment_operators = [
"=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>="
"=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="
]
lvalue = self.parse_ternary_expression()
if self.tokens.peek() in assignment_operators:
if not hasattr(lvalue, "declaration"):
if lvalue.const():
 
self.tokens.error(
"left hand operand of assignment is not modifiable"
)
"left hand operand of assignment is not modifiable")
 
operator = self.tokens.get()
if operator == "=":
expression = self.parse_ternary_expression()
else:
expression = Binary(
operator[:-1],
lvalue,
self.parse_ternary_expression(),
self.allocator
)
if not compatible(lvalue.type_, expression.type_):
self.tokens.error(
"type mismatch in assignment"
)
 
expression = self.parse_ternary_expression()
left = lvalue
left, expression = self.coerce_types(left, expression)
expression = Binary(operator[:-1], left, expression)
 
if expression.type_() != lvalue.type_():
if expression.type_() == "int" and lvalue.type_() == "float":
expression = IntToFloat(expression)
elif expression.type_() == "float" and lvalue.type_() == "int":
expression = FloatToInt(expression)
else:
self.tokens.error(
"type mismatch in assignment expected: %s actual: %s"%(
lvalue.type_(),
expression.type_()))
 
return Assignment(lvalue, expression, self.allocator)
else:
return lvalue
264,10 → 327,9
self.tokens.expect("if")
self.tokens.expect("(")
if_.expression = self.parse_expression()
if if_.expression.type_ not in ["unsigned", "int", "short", "long", "char"]:
if if_.expression.type_() not in ["unsigned", "int", "short", "long", "char"]:
self.tokens.error(
"if statement conditional must be an integer like expression"
)
"if statement conditional must be an integer like expression")
self.tokens.expect(")")
if_.true_statement = self.parse_statement()
if self.tokens.peek() == "else":
283,10 → 345,9
self.tokens.expect("switch")
self.tokens.expect("(")
expression = self.parse_expression()
if expression.type_ not in ["unsigned", "int", "short", "long", "char"]:
if expression.type_() not in ["unsigned", "int", "short", "long", "char"]:
self.tokens.error(
"switch statement expression must be an integer like expression"
)
"switch statement expression must be an integer like expression")
self.tokens.expect(")")
stored_loop = self.loop
self.loop = switch
300,21 → 361,19
def parse_case(self):
self.tokens.expect("case")
expression = self.parse_expression()
if expression.type_ not in ["int"]:
if expression.type_() not in ["int"]:
self.tokens.error(
"case expression must be an integer like expression"
)
"case expression must be an integer like expression")
self.tokens.expect(":")
try:
expression = value(expression)
expression = expression.value()
case = Case()
self.loop.cases[expression] = case
self.loop.cases[expression] = case
except NotConstant:
self.tokens.error("case expression must be constant")
except AttributeError:
self.tokens.error(
"case statements may only be use inside a switch statment"
)
"case statements may only be use inside a switch statment")
return case
 
def parse_default(self):
323,12 → 382,10
default = Default()
if not hasattr(self.loop, "cases"):
self.tokens.error(
"default statements may only be used inside a switch statment"
)
"default statements may only be used inside a switch statment")
if hasattr(self.loop, "default"):
self.tokens.error(
"A switch statement may only have one default statement"
)
"A switch statement may only have one default statement")
self.loop.default=default
return default
 
348,10 → 405,9
break_ = Break()
break_.loop = loop
if_.allocator = self.allocator
if expression.type_ not in ["int"]:
if expression.type_() not in ["int"]:
self.tokens.error(
"if statement conditional must be an integer like expression"
)
"while statement conditional must be an integer like expression")
if_.expression = expression
if_.false_statement = break_
if_.true_statement = statement
368,10 → 424,16
self.tokens.expect(";")
if self.tokens.peek() != ";":
for_.expression = self.parse_expression()
if for_.expression.type_ not in ["unsigned", "int", "short", "long", "char"]:
if for_.expression.type_() not in [
"unsigned",
"int",
"short",
"long",
"char"]:
 
self.tokens.error(
"for statement conditional must be an integer like expression"
)
"For statement conditional must be an integer like expression")
 
self.tokens.expect(";")
if self.tokens.peek() != ")":
for_.statement2 = self.parse_discard()
384,7 → 446,7
 
def parse_block(self):
block = Block()
stored_scope = self.scope
stored_scope = copy(self.scope)
self.tokens.expect("{")
block.statements = []
while self.tokens.peek() != "}":
397,9 → 459,16
self.tokens.expect("{")
members = {}
while self.tokens.peek() != "}":
type_, size, signed = self.parse_type_specifier()
type_, size, signed, const = self.parse_type_specifier()
name = self.tokens.get()
members[name] = self.parse_declaration(type_, size, signed, name)
 
members[name] = self.parse_declaration(
type_,
size,
signed,
const,
name)
 
self.tokens.expect(";")
self.tokens.expect("}")
return members
429,10 → 498,17
self.scope[name] = instance
return instance
 
def parse_global_declaration(self, type_, size, signed, name):
def parse_global_declaration(self, type_, size, signed, const, name):
instances = []
while True:
instance = self.parse_declaration(type_, size, signed, name).instance()
 
instance = self.parse_declaration(
type_,
size,
signed,
const,
name).instance()
 
self.scope[name] = instance
instances.append(instance)
if self.tokens.peek() == ",":
444,11 → 520,18
return CompoundDeclaration(instances)
 
def parse_compound_declaration(self):
type_, size, signed = self.parse_type_specifier()
type_, size, signed, const = self.parse_type_specifier()
instances = []
while True:
name = self.tokens.get()
instance = self.parse_declaration(type_, size, signed, name).instance()
 
instance = self.parse_declaration(
type_,
size,
signed,
const,
name).instance()
 
self.scope[name] = instance
instances.append(instance)
if self.tokens.peek() == ",":
459,17 → 542,24
self.tokens.expect(";")
return CompoundDeclaration(instances)
 
def parse_declaration(self, type_, size, signed, name):
def parse_declaration(self, type_, size, signed, const, name):
#struct declaration
if type_ in self.structs:
declaration = self.scope[type_]
elif type_ in ["int"]:
#array declaration
elif type_ in ["int", "float"]:
#array declaration
if self.tokens.peek() == "[":
array_size = None
self.tokens.expect("[")
if self.tokens.peek() != "]":
array_size = int(self.tokens.get())
size_expression = self.parse_ternary_expression()
if size_expression.type_() != "int":
self.tokens.error("Array size must be an integer like expression")
try:
array_size = size_expression.value()
except NotConstant:
self.tokens.error("Array size must be constant")
 
self.tokens.expect("]")
initializer = None
if self.tokens.peek() == "=":
478,32 → 568,49
initializer = [ord(i) for i in initializer.strip('"').decode("string_escape")] + [0]
array_size = len(initializer)
if array_size is None:
self.tokens.error("array size must be specified if not initialized")
 
self.tokens.error(
"array size must be specified if not initialized")
 
array_type=type_+"[]"
initialize_memory = self.initialize_memory
declaration = ArrayDeclaration(self.allocator,
array_size,
array_type,
type_,
size,
signed,
initializer,
self.initialize_memory)
declaration = ArrayDeclaration(
self.allocator,
array_size,
array_type,
type_,
size,
signed,
initializer,
self.initialize_memory)
 
#simple variable declaration
#simple variable declaration
else:
if self.tokens.peek() == "=":
self.tokens.expect("=")
initializer = self.parse_ternary_expression()
else:
initializer = Constant(0)
initializer = Constant(0, type_, size, signed)
 
if type_ != initializer.type_():
 
if type_ == "int" and initializer.type_() == "float":
initializer = FloatToInt(initializer)
elif type_ == "float" and initializer.type_() == "int":
initializer = IntToFloat(initializer)
else:
self.tokens.error(
"type mismatch in intializer expected: %s actual: %s"%(
type_,
intitializer.type_()))
declaration = VariableDeclaration(
self.allocator,
initializer,
self.allocator,
initializer,
name,
type_,
size,
signed
signed,
const
)
 
return declaration
536,45 → 643,65
expression = AND(expression, self.parse_binary_expression(["|"]))
return expression
 
def substitute_function(self, operator, left, right):
def substitute_function(self, binary_expression):
 
"""
For some operations are more easily implemented in sofftware.
This function substitutes a call to the builtin library function.
"""
 
functions = {
"False,int,int,4,/" : "long_unsigned_divide_xxxx",
"True,int,int,4,/" : "long_divide_xxxx",
"False,int,int,2,/" : "unsigned_divide_xxxx",
"True,int,int,2,/" : "divide_xxxx",
"False,int,int,4,%" : "long_unsigned_modulo_xxxx",
"True,int,int,4,%" : "long_modulo_xxxx",
"False,int,int,2,%" : "unsigned_modulo_xxxx",
"True,int,int,2,%" : "modulo_xxxx",
"True,float,float,4,==" : "float_equal_xxxx",
"True,float,float,4,!=" : "float_ne_xxxx",
"True,float,float,4,<" : "float_lt_xxxx",
"True,float,float,4,>" : "float_gt_xxxx",
"True,float,float,4,<=" : "float_le_xxxx",
"True,float,float,4,>=" : "float_ge_xxxx",
}
 
#select a function that matches the template.
signature = ",".join([
str(binary_expression.signed()),
binary_expression.left.type_(),
binary_expression.right.type_(),
str(binary_expression.size()),
binary_expression.operator])
 
#Some things can't be implemented in verilog, substitute them with a function
if operator in ["/", "%"]:
function_call = FunctionCall()
function_call.arguments = [left, right]
if operator == "/":
if left.signed and right.signed:
if max(left.size, right.size) == 4:
function_call.function = self.scope["long_divide_xxxx"]
else:
function_call.function = self.scope["divide_xxxx"]
else:
if max(left.size, right.size) == 4:
function_call.function = self.scope["long_unsigned_divide_xxxx"]
else:
function_call.function = self.scope["unsigned_divide_xxxx"]
elif operator == "%":
if left.signed and right.signed:
if max(left.size, right.size) == 4:
function_call.function = self.scope["long_modulo_xxxx"]
else:
function_call.function = self.scope["modulo_xxxx"]
else:
if max(left.size, right.size) == 4:
function_call.function = self.scope["long_unsigned_modulo_xxxx"]
else:
function_call.function = self.scope["unsigned_modulo_xxxx"]
function_call.type_ = function_call.function.type_
function_call.size = function_call.function.size
function_call.signed = function_call.function.signed
if signature in functions:
function = self.scope[functions[signature]]
function_call = FunctionCall(function)
function_call.arguments = [binary_expression.left, binary_expression.right]
return function_call
else:
return Binary(
operator,
left,
right,
self.allocator
)
return binary_expression
 
def coerce_types(self, left, right):
 
"""
Convert numeric types in expressions.
"""
 
if left.type_() != right.type_():
if left.type_() == "float" and right.type_() == "int":
return left, IntToFloat(right)
elif left.type_() == "int" and right.type_() == "float":
return IntToFloat(left), right
else:
self.tokens.error("Incompatible types : %s %s"%(
left.type_(),
right.type_()))
 
return left, right
 
def parse_binary_expression(self, operators):
operator_precedence = {
"|": ["^"],
586,37 → 713,42
"+": ["*", "/", "%"],
}
if operators[0] not in operator_precedence:
expression = self.parse_unary_expression()
left = self.parse_unary_expression()
while self.tokens.peek() in operators:
operator = self.tokens.get()
right = self.parse_unary_expression()
expression = self.substitute_function(operator, expression, right)
return expression
left, right = self.coerce_types(left, right)
left = Binary(operator, left, right)
left = self.substitute_function(left)
return left
else:
next_operators = operator_precedence[operators[0]]
expression = self.parse_binary_expression(next_operators)
left = self.parse_binary_expression(next_operators)
while self.tokens.peek() in operators:
expression = Binary(
self.tokens.get(),
expression,
self.parse_binary_expression(next_operators),
self.allocator
)
return expression
operator = self.tokens.get()
right = self.parse_binary_expression(next_operators)
left, right = self.coerce_types(left, right)
left = Binary(operator, left, right)
left = self.substitute_function(left)
return left
 
def parse_unary_expression(self):
if self.tokens.peek() == "!":
operator = self.tokens.get()
expression = self.parse_postfix_expression()
return Binary("==", expression, Constant(0), self.allocator)
return Binary("==", expression, Constant(0))
elif self.tokens.peek() == "-":
operator = self.tokens.get()
expression = self.parse_postfix_expression()
return Binary("-", Constant(0), expression, self.allocator)
return Binary("-", Constant(0,
expression.type_(),
expression.size(),
expression.signed()),
expression)
elif self.tokens.peek() == "~":
operator = self.tokens.get()
expression = self.parse_postfix_expression()
return Unary("~", expression, self.allocator)
return Unary("~", expression)
elif self.tokens.peek() == "sizeof":
operator = self.tokens.get()
expression = self.parse_unary_expression()
630,7 → 762,7
operator = self.tokens.get()
expression = PostIncrement(
operator[:-1],
expression,
expression,
self.allocator
)
return expression
700,7 → 832,10
return self.parse_file_read()
if name == "file_write":
return self.parse_file_write()
function_call = FunctionCall()
if name not in self.scope:
self.tokens.error("Unknown function: %s"%name)
function = self.scope[name]
function_call = FunctionCall(function)
function_call.arguments = []
self.tokens.expect("(")
while self.tokens.peek() != ")":
711,13 → 846,7
break
self.tokens.expect(")")
 
if name not in self.scope:
self.tokens.error("Unknown function: %s"%name)
 
function_call.function = self.scope[name]
function_call.type_ = function_call.function.type_
function_call.size = function_call.function.size
function_call.signed = function_call.function.signed
required_arguments = len(function_call.function.arguments)
actual_arguments = len(function_call.arguments)
if required_arguments != actual_arguments:
724,22 → 853,29
self.tokens.error("Function %s takes %s arguments %s given."%(
name,
len(function_call.function.arguments),
len(function_call.arguments)
))
len(function_call.arguments)))
required_arguments = function_call.function.arguments
actual_arguments = function_call.arguments
corrected_arguments = []
for required, actual in zip(required_arguments, actual_arguments):
if not compatible(required.type_, actual.type_):
self.tokens.error("Type mismatch expected type : %s got: %s."%(
required.type_,
actual.type_
))
if not compatible(required, actual):
if actual.type_() == "int" and required.type_() == "float":
actual = IntToFloat(actual)
elif actual.type_() == "float" and required.type_() == "int":
actual = FloatToInt(actual)
else:
self.tokens.error(
"type mismatch in assignment expected: %s actual: %s"%(
required.type_(),
actual.type_()))
corrected_arguments.append(actual)
function_call.arguments = corrected_arguments
 
 
return function_call
 
def parse_number(self):
token = self.tokens.get()
type_ = "int"
size = 2
signed = True
if token.startswith("'"):
754,18 → 890,36
size = len(initializer)
initialize_memory = self.initialize_memory
declaration = ArrayDeclaration(
self.allocator,
size,
"int[]",
"int",
2,
False,
initializer,
self.allocator,
size,
"int[]",
"int",
2,
False,
initializer,
self.initialize_memory)
return declaration.instance()
return ConstArray(declaration.instance())
except SyntaxError:
self.tokens.error("%s is not a character literal"%token)
elif "." in token:
#float literal
try:
type_ = "float"
signed = True
size = 4
token = token.upper().replace("F", "")
token = token.upper().replace("L", "")
value = float(eval(token))
 
try:
byte_value = struct.pack(">f", value)
except OverflowError:
self.tokens.error("value too large")
 
except SyntaxError:
self.tokens.error("%s is not a floating point literal"%token)
else:
#integer literal
try:
if "U" in token.upper():
signed = False
787,34 → 941,45
 
except SyntaxError:
self.tokens.error("%s is not an integer literal"%token)
return Constant(value, size, signed)
 
return Constant(value, type_, size, signed)
 
def parse_variable(self, name):
if name not in self.scope:
self.tokens.error("Unknown variable: %s"%name)
instance = self.scope[name]
return self.parse_variable_array_struct(instance)
 
def parse_variable_array_struct(self, instance):
if instance.type_ in ["unsigned", "int", "short", "long", "char"]:
return Variable(instance, self.allocator)
elif instance.type_.endswith("[]"):
if instance.type_() in numeric_types:
 
if not hasattr(instance, "reference"):
 
self.tokens.error(
"Not an expression")
 
return Variable(instance)
elif instance.type_().endswith("[]"):
if self.tokens.peek() == "[":
self.tokens.expect("[")
index_expression = self.parse_expression()
self.tokens.expect("]")
if index_expression.type_ not in ["unsigned", "int", "short", "long", "char"]:
if index_expression.type_() not in ["int"]:
 
self.tokens.error(
"array indices must be an integer like expression"
)
return ArrayIndex(instance, index_expression, self.allocator)
"Array indices must be an integer like expression")
 
return ArrayIndex(instance, index_expression)
else:
return Array(instance, self.allocator)
elif instance.type_ == "struct":
self.tokens.expect(".")
member = self.tokens.get()
instance = instance.members[member]
return self.parse_variable_array_struct(instance)
return Array(instance)
elif instance.type_().startswith("struct"):
if self.tokens.peek() == ".":
self.tokens.expect(".")
member = self.tokens.get()
instance = instance.members[member]
return self.parse_variable_array_struct(instance)
else:
return Struct(instance)
 
def compatible(left, right):
return left == right
return left.type_() == right.type_()
/chips/compiler/verilog_area.py
14,22 → 14,24
__copyright__ = "Copyright (C) 2013, Jonathan P Dawson"
__version__ = "0.1"
 
import fpu
 
def unique(l):
 
"""In the absence of set in older python implementations, make list values unique"""
"""In the absence of set in older python implementations, make list values unique"""
 
return dict(zip(l, l)).keys()
return dict(zip(l, l)).keys()
 
def log2(instructions):
 
"""Integer only algorithm to calculate the number of bits needed to store a number"""
"""Integer only algorithm to calculate the number of bits needed to store a number"""
 
bits = 1
power = 2
while power < instructions:
bits += 1
power *= 2
return bits
bits = 1
power = 2
while power < instructions:
bits += 1
power *= 2
return bits
 
def print_verilog_literal(size, value):
 
60,7 → 62,7
if instruction["srcb"] == wait_2_for:
wait = max(wait, 2)
for i in range(wait):
new_instructions.append({"op":"nop"})
new_instructions.append({"op":"nop"})
new_instructions.append(instruction)
 
if instruction["op"] != "label":
84,10 → 86,12
encoded_instruction["src"] = 0
encoded_instruction["srcb"] = 0
encoded_instruction["literal"] = 0
encoded_instruction["float"] = True
opcode["op"] = instruction["op"]
opcode["right"] = False
opcode["unsigned"] = False
opcode["literal"] = False
opcode["literal"] = False
opcode["float"] = False
 
if "signed" in instruction:
opcode["unsigned"] = not instruction["signed"]
95,8 → 99,11
if "element_size" in instruction:
opcode["element_size"] = instruction["element_size"]
 
if "file_name" in instruction:
opcode["file_name"] = instruction["file_name"]
 
if "file" in instruction:
opcode["file_"] = instruction["file"]
opcode["file"] = instruction["file"]
 
if "line" in instruction:
opcode["line"] = instruction["line"]
125,6 → 132,11
opcode["right"] = True
encoded_instruction["literal"] = instruction["right"]
 
if "type" in instruction:
if instruction["type"] == "float":
opcode["float"] = True
encoded_instruction["float"] = True
 
if "literal" in instruction:
opcode["literal"] = True
encoded_instruction["literal"] = instruction["literal"]
147,389 → 159,539
 
def calculate_jumps(instructions):
 
"""change symbolic labels into numeric addresses"""
"""change symbolic labels into numeric addresses"""
 
#calculate the values of jump locations
location = 0
labels = {}
new_instructions = []
for instruction in instructions:
if instruction["op"] == "label":
labels[instruction["label"]] = location
else:
new_instructions.append(instruction)
location += 1
instructions = new_instructions
#calculate the values of jump locations
location = 0
labels = {}
new_instructions = []
for instruction in instructions:
if instruction["op"] == "label":
labels[instruction["label"]] = location
else:
new_instructions.append(instruction)
location += 1
instructions = new_instructions
 
#substitue real values for labeled jump locations
for instruction in instructions:
if "label" in instruction:
instruction["label"]=labels[instruction["label"]]
#substitue real values for labeled jump locations
for instruction in instructions:
if "label" in instruction:
instruction["label"]=labels[instruction["label"]]
 
return instructions
return instructions
 
def generate_declarations(instructions, no_tb_mode, register_bits, opcode_bits):
 
"""Generate verilog declarations"""
"""Generate verilog declarations"""
 
#list all inputs and outputs used in the program
inputs = unique([i["input"] for i in instructions if "input" in i])
outputs = unique([i["output"] for i in instructions if "output" in i])
input_files = unique([i["file_name"] for i in instructions if "file_read" == i["op"]])
output_files = unique([i["file_name"] for i in instructions if "file_write" == i["op"]])
testbench = not inputs and not outputs and not no_tb_mode
#list all inputs and outputs used in the program
inputs = unique([i["input"] for i in instructions if "input" in i])
outputs = unique([i["output"] for i in instructions if "output" in i])
input_files = unique([i["file_name"] for i in instructions if "file_read" == i["op"]])
output_files = unique([i["file_name"] for i in instructions if "file_write" == i["op"]])
testbench = not inputs and not outputs and not no_tb_mode
 
#Do not generate a port in testbench mode
inports = [
("input_" + i, 16) for i in inputs
] + [
("input_" + i + "_stb", 1) for i in inputs
] + [
("output_" + i + "_ack", 1) for i in outputs
]
#Do not generate a port in testbench mode
inports = [
("input_" + i, 16) for i in inputs
] + [
("input_" + i + "_stb", 1) for i in inputs
] + [
("output_" + i + "_ack", 1) for i in outputs
]
 
outports = [
("output_" + i, 16) for i in outputs
] + [
("output_" + i + "_stb", 1) for i in outputs
] + [
("input_" + i + "_ack", 1) for i in inputs
]
outports = [
("output_" + i, 16) for i in outputs
] + [
("output_" + i + "_stb", 1) for i in outputs
] + [
("input_" + i + "_ack", 1) for i in inputs
]
 
#create list of signals
signals = [
("timer", 16),
("timer_enable", 1),
("stage_0_enable", 1),
("stage_1_enable", 1),
("stage_2_enable", 1),
("program_counter", log2(len(instructions))),
("program_counter_0", log2(len(instructions))),
("instruction_0", 32 + register_bits*2 + opcode_bits),
("opcode_0", opcode_bits),
("dest_0", register_bits),
("src_0", register_bits),
("srcb_0", register_bits),
("literal_0", 32),
("program_counter_1", log2(len(instructions))),
("opcode_1", opcode_bits),
("dest_1", register_bits),
("register_1", 32),
("registerb_1", 32),
("literal_1", 32),
("dest_2", register_bits),
("result_2", 32),
("write_enable_2", 1),
("address_2", 16),
("data_out_2", 16),
("data_in_2", 16),
("memory_enable_2", 1),
("address_4", 16),
("data_out_4", 32),
("data_in_4", 32),
("memory_enable_4", 1),
] + [
("s_output_" + i + "_stb", 16) for i in outputs
] + [
("s_output_" + i, 16) for i in outputs
] + [
("s_input_" + i + "_ack", 16) for i in inputs
]
#create list of signals
signals = [
("timer", 16),
("timer_enable", 1),
("stage_0_enable", 1),
("stage_1_enable", 1),
("stage_2_enable", 1),
("program_counter", log2(len(instructions))),
("program_counter_0", log2(len(instructions))),
("instruction_0", 32 + register_bits*2 + opcode_bits),
("opcode_0", opcode_bits),
("dest_0", register_bits),
("src_0", register_bits),
("srcb_0", register_bits),
("literal_0", 32),
("program_counter_1", log2(len(instructions))),
("opcode_1", opcode_bits),
("dest_1", register_bits),
("register_1", 32),
("registerb_1", 32),
("literal_1", 32),
("dest_2", register_bits),
("result_2", 32),
("write_enable_2", 1),
("address_2", 16),
("data_out_2", 16),
("data_in_2", 16),
("memory_enable_2", 1),
("address_4", 16),
("data_out_4", 32),
("data_in_4", 32),
("memory_enable_4", 1),
] + [
("s_output_" + i + "_stb", 16) for i in outputs
] + [
("s_output_" + i, 16) for i in outputs
] + [
("s_input_" + i + "_ack", 16) for i in inputs
]
 
if testbench:
signals.append(("clk", 1))
signals.append(("rst", 1))
else:
inports.append(("clk", 1))
inports.append(("rst", 1))
if testbench:
signals.append(("clk", 1))
signals.append(("rst", 1))
else:
inports.append(("clk", 1))
inports.append(("rst", 1))
 
return inputs, outputs, input_files, output_files, testbench, inports, outports, signals
return inputs, outputs, input_files, output_files, testbench, inports, outports, signals
 
def generate_CHIP(input_file,
name,
instructions,
output_file,
registers,
memory_size_2,
memory_size_4,
def floating_point_enables(instruction_set):
enable_adder = False
enable_multiplier = False
enable_divider = False
enable_int_to_float = False
enable_float_to_int = False
for i in instruction_set:
if i["op"] == "+" and i["float"]:
enable_adder = True
if i["op"] == "-" and i["float"]:
enable_adder = True
if i["op"] == "*" and i["float"]:
enable_multiplier = True
if i["op"] == "/" and i["float"]:
enable_divider = True
if i["op"] == "int_to_float":
enable_int_to_float = True
if i["op"] == "float_to_int":
enable_float_to_int = True
return (
enable_adder,
enable_multiplier,
enable_divider,
enable_int_to_float,
enable_float_to_int)
 
def generate_CHIP(input_file,
name,
instructions,
output_file,
registers,
memory_size_2,
memory_size_4,
initialize_memory,
memory_content_2,
memory_content_4,
memory_content_2,
memory_content_4,
no_tb_mode=False):
 
"""A big ugly function to crunch through all the instructions and generate the CHIP equivilent"""
"""A big ugly function to crunch through all the instructions and generate the CHIP equivilent"""
 
instructions = remove_register_hazards(instructions)
instructions = calculate_jumps(instructions)
instruction_set, instruction_memory = generate_instruction_set(instructions)
register_bits = log2(len(registers));
opcode_bits = log2(len(instruction_set));
instruction_bits = 32 + register_bits*2 + opcode_bits
declarations = generate_declarations(instructions, no_tb_mode, register_bits, opcode_bits)
inputs, outputs, input_files, output_files, testbench, inports, outports, signals = declarations
instructions = remove_register_hazards(instructions)
instructions = calculate_jumps(instructions)
instruction_set, instruction_memory = generate_instruction_set(instructions)
register_bits = log2(len(registers));
opcode_bits = log2(len(instruction_set));
instruction_bits = 32 + register_bits*2 + opcode_bits
declarations = generate_declarations(instructions, no_tb_mode, register_bits, opcode_bits)
inputs, outputs, input_files, output_files, testbench, inports, outports, signals = declarations
enable_adder, enable_multiplier, enable_divider, enable_int_to_float, enable_float_to_int = floating_point_enables(instruction_set)
 
#output the code in verilog
output_file.write("//name : %s\n"%name)
output_file.write("//tag : c components\n")
for i in inputs:
output_file.write("//input : input_%s:16\n"%i)
for i in outputs:
output_file.write("//output : output_%s:16\n"%i)
output_file.write("//source_file : %s\n"%input_file)
output_file.write("///%s\n"%"".join(["=" for i in name]))
output_file.write("///\n")
output_file.write("///*Created by C2CHIP*\n\n")
#output the code in verilog
output_file.write("//////////////////////////////////////////////////////////////////////////////\n")
output_file.write("//name : %s\n"%name)
for i in inputs:
output_file.write("//input : input_%s:16\n"%i)
for i in outputs:
output_file.write("//output : output_%s:16\n"%i)
output_file.write("//source_file : %s\n"%input_file)
output_file.write("///%s\n"%"".join(["=" for i in name]))
output_file.write("///\n")
output_file.write("///Created by C2CHIP\n\n")
 
if enable_adder:
output_file.write(fpu.adder)
if enable_divider:
output_file.write(fpu.divider)
if enable_multiplier:
output_file.write(fpu.multiplier)
if enable_int_to_float:
output_file.write(fpu.int_to_float)
if enable_float_to_int:
output_file.write(fpu.float_to_int)
 
output_file.write("//////////////////////////////////////////////////////////////////////////////\n")
output_file.write("// Register Allocation\n")
output_file.write("// ===================\n")
output_file.write("// %s %s %s \n"%("Register".center(20), "Name".center(20), "Size".center(20)))
for register, definition in registers.iteritems():
register_name, size = definition
output_file.write("// %s %s %s \n"%(str(register).center(20), register_name.center(20), str(size).center(20)))
 
output_file.write(" \n`timescale 1ns/1ps\n")
output_file.write("module %s"%name)
output_file.write("//////////////////////////////////////////////////////////////////////////////\n")
output_file.write("// Register Allocation\n")
output_file.write("// ===================\n")
output_file.write("// %s %s %s \n"%("Register".center(20), "Name".center(20), "Size".center(20)))
for register, definition in registers.iteritems():
register_name, size = definition
output_file.write("// %s %s %s \n"%(str(register).center(20), register_name.center(20), str(size).center(20)))
 
all_ports = [name for name, size in inports + outports]
if all_ports:
output_file.write("(")
output_file.write(",".join(all_ports))
output_file.write(");\n")
else:
output_file.write(";\n")
 
output_file.write(" integer file_count;\n")
output_file.write("module %s"%name)
 
input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)]))
for i in input_files.values():
output_file.write(" integer %s;\n"%i)
all_ports = [name for name, size in inports + outports]
if all_ports:
output_file.write("(")
output_file.write(",".join(all_ports))
output_file.write(");\n")
else:
output_file.write(";\n")
 
output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)]))
for i in output_files.values():
output_file.write(" integer %s;\n"%i)
output_file.write(" integer file_count;\n")
 
 
def write_declaration(object_type, name, size, value=None):
if size == 1:
output_file.write(object_type)
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
else:
output_file.write(object_type)
output_file.write("[%i:0]"%(size-1))
output_file.write(" ")
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
if enable_adder:
generate_adder_signals(output_file)
if enable_multiplier:
generate_multiplier_signals(output_file)
if enable_divider:
generate_divider_signals(output_file)
if enable_int_to_float:
generate_int_to_float_signals(output_file)
if enable_float_to_int:
generate_float_to_int_signals(output_file)
 
for name, size in inports:
write_declaration(" input ", name, size)
output_file.write(" real fp_value;\n")
if enable_adder or enable_multiplier or enable_divider or enable_int_to_float or enable_float_to_int:
output_file.write(" parameter wait_go = 2'd0,\n")
output_file.write(" write_a = 2'd1,\n")
output_file.write(" write_b = 2'd2,\n")
output_file.write(" read_z = 2'd3;\n")
 
for name, size in outports:
write_declaration(" output ", name, size)
input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)]))
for i in input_files.values():
output_file.write(" integer %s;\n"%i)
 
for name, size in signals:
write_declaration(" reg ", name, size)
output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)]))
for i in output_files.values():
output_file.write(" integer %s;\n"%i)
 
memory_size_2 = int(memory_size_2)
memory_size_4 = int(memory_size_4)
if memory_size_2:
output_file.write(" reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1))
if memory_size_4:
output_file.write(" reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1))
 
output_file.write(" reg [%s:0] instructions [%i:0];\n"%(instruction_bits-1, len(instructions)-1))
output_file.write(" reg [31:0] registers [%i:0];\n"%(len(registers)-1))
def write_declaration(object_type, name, size, value=None):
if size == 1:
output_file.write(object_type)
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
else:
output_file.write(object_type)
output_file.write("[%i:0]"%(size-1))
output_file.write(" ")
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
 
for name, size in inports:
write_declaration(" input ", name, size)
 
#generate clock and reset in testbench mode
if testbench:
for name, size in outports:
write_declaration(" output ", name, size)
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // CLOCK AND RESET GENERATION \n")
output_file.write(" // \n")
output_file.write(" // This file was generated in test bench mode. In this mode, the verilog \n")
output_file.write(" // output file can be executed directly within a verilog simulator. \n")
output_file.write(" // In test bench mode, a simulated clock and reset signal are generated within\n")
output_file.write(" // the output file. \n")
output_file.write(" // Verilog files generated in testbecnch mode are not suitable for synthesis, \n")
output_file.write(" // or for instantiation within a larger design.\n")
for name, size in signals:
write_declaration(" reg ", name, size)
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" rst <= 1'b1;\n")
output_file.write(" #50 rst <= 1'b0;\n")
output_file.write(" end\n\n")
memory_size_2 = int(memory_size_2)
memory_size_4 = int(memory_size_4)
if memory_size_2:
output_file.write(" reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1))
if memory_size_4:
output_file.write(" reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1))
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" clk <= 1'b0;\n")
output_file.write(" while (1) begin\n")
output_file.write(" #5 clk <= ~clk;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" reg [%s:0] instructions [%i:0];\n"%(instruction_bits-1, len(instructions)-1))
output_file.write(" reg [31:0] registers [%i:0];\n"%(len(registers)-1))
 
#Generate a state machine to execute the instructions
binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=",
"<=", "==", "!="]
 
#generate clock and reset in testbench mode
if testbench:
 
if initialize_memory and (memory_content_2 or memory_content_4):
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // CLOCK AND RESET GENERATION \n")
output_file.write(" // \n")
output_file.write(" // This file was generated in test bench mode. In this mode, the verilog \n")
output_file.write(" // output file can be executed directly within a verilog simulator. \n")
output_file.write(" // In test bench mode, a simulated clock and reset signal are generated within\n")
output_file.write(" // the output file. \n")
output_file.write(" // Verilog files generated in testbecnch mode are not suitable for synthesis, \n")
output_file.write(" // or for instantiation within a larger design.\n")
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // MEMORY INITIALIZATION \n")
output_file.write(" // \n")
output_file.write(" // In order to reduce program size, array contents have been stored into \n")
output_file.write(" // memory at initialization. In an FPGA, this will result in the memory being \n")
output_file.write(" // initialized when the FPGA configures. \n")
output_file.write(" // Memory will not be re-initialized at reset. \n")
output_file.write(" // Dissable this behaviour using the no_initialize_memory switch \n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" rst <= 1'b1;\n")
output_file.write(" #50 rst <= 1'b0;\n")
output_file.write(" end\n\n")
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for location, content in memory_content_2.iteritems():
output_file.write(" memory_2[%s] = %s;\n"%(location, content))
for location, content in memory_content_4.iteritems():
output_file.write(" memory_4[%s] = %s;\n"%(location, content))
output_file.write(" end\n\n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" clk <= 1'b0;\n")
output_file.write(" while (1) begin\n")
output_file.write(" #5 clk <= ~clk;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
#Instance Floating Point Arithmetic
if enable_adder or enable_multiplier or enable_divider or enable_int_to_float or enable_float_to_int:
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // INSTRUCTION INITIALIZATION \n")
output_file.write(" // \n")
output_file.write(" // Initialise the contents of the instruction memory \n")
output_file.write(" //\n")
output_file.write(" // Intruction Set\n")
output_file.write(" // ==============\n")
for num, opcode in enumerate(instruction_set):
output_file.write(" // %s %s\n"%(num, opcode))
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // Floating Point Arithmetic \n")
output_file.write(" // \n")
output_file.write(" // Generate IEEE 754 single precision divider, adder and multiplier \n")
output_file.write(" // \n")
 
output_file.write(" // Intructions\n")
output_file.write(" // ===========\n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for location, instruction in enumerate(instruction_memory):
output_file.write(" instructions[%s] = {%s, %s, %s, %s};//%s\n"%(
location,
print_verilog_literal(opcode_bits, instruction["op"]),
print_verilog_literal(register_bits, instruction["dest"]),
print_verilog_literal(register_bits, instruction["src"]),
print_verilog_literal(32, instruction["srcb"] | instruction["literal"]),
instruction["comment"]))
output_file.write(" end\n\n")
if enable_divider:
connect_divider(output_file)
if enable_multiplier:
connect_multiplier(output_file)
if enable_adder:
connect_adder(output_file)
if enable_int_to_float:
connect_int_to_float(output_file)
if enable_float_to_int:
connect_float_to_int(output_file)
 
if input_files or output_files:
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // OPEN FILES \n")
output_file.write(" // \n")
output_file.write(" // Open all files used at the start of the process \n")
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for file_name, file_ in input_files.iteritems():
output_file.write(" %s = $fopenr(\"%s\");\n"%(file_, file_name))
for file_name, file_ in output_files.iteritems():
output_file.write(" %s = $fopen(\"%s\");\n"%(file_, file_name))
output_file.write(" end\n\n")
#Generate a state machine to execute the instructions
binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=",
"<=", "==", "!="]
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // CPU IMPLEMENTAION OF C PROCESS \n")
output_file.write(" // \n")
output_file.write(" // This section of the file contains a CPU implementing the C process. \n")
 
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
if initialize_memory and (memory_content_2 or memory_content_4):
 
if memory_size_2:
output_file.write(" //implement memory for 2 byte x n arrays\n")
output_file.write(" if (memory_enable_2 == 1'b1) begin\n")
output_file.write(" memory_2[address_2] <= data_in_2;\n")
output_file.write(" end\n")
output_file.write(" data_out_2 <= memory_2[address_2];\n")
output_file.write(" memory_enable_2 <= 1'b0;\n\n")
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // MEMORY INITIALIZATION \n")
output_file.write(" // \n")
output_file.write(" // In order to reduce program size, array contents have been stored into \n")
output_file.write(" // memory at initialization. In an FPGA, this will result in the memory being \n")
output_file.write(" // initialized when the FPGA configures. \n")
output_file.write(" // Memory will not be re-initialized at reset. \n")
output_file.write(" // Dissable this behaviour using the no_initialize_memory switch \n")
 
if memory_size_4:
output_file.write(" //implement memory for 4 byte x n arrays\n")
output_file.write(" if (memory_enable_4 == 1'b1) begin\n")
output_file.write(" memory_4[address_4] <= data_in_4;\n")
output_file.write(" end\n")
output_file.write(" data_out_4 <= memory_4[address_4];\n")
output_file.write(" memory_enable_4 <= 1'b0;\n\n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for location, content in memory_content_2.iteritems():
output_file.write(" memory_2[%s] = %s;\n"%(location, content))
for location, content in memory_content_4.iteritems():
output_file.write(" memory_4[%s] = %s;\n"%(location, content))
output_file.write(" end\n\n")
 
output_file.write(" write_enable_2 <= 0;\n")
 
output_file.write(" //stage 0 instruction fetch\n")
output_file.write(" if (stage_0_enable) begin\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" instruction_0 <= instructions[program_counter];\n")
output_file.write(" opcode_0 = instruction_0[%s:%s];\n"%(
register_bits * 2 + opcode_bits + 31,
register_bits * 2 + 32))
output_file.write(" dest_0 = instruction_0[%s:%s];\n"%(
register_bits * 2 + 31,
register_bits + 32))
output_file.write(" src_0 = instruction_0[%s:32];\n"%(
register_bits + 31))
output_file.write(" srcb_0 = instruction_0[%s:0];\n"%(register_bits-1))
output_file.write(" literal_0 = instruction_0[31:0];\n")
output_file.write(" if(write_enable_2) begin\n")
output_file.write(" registers[dest_2] <= result_2;\n")
output_file.write(" end\n")
output_file.write(" program_counter_0 <= program_counter;\n")
output_file.write(" program_counter <= program_counter + 1;\n")
output_file.write(" end\n\n")
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // INSTRUCTION INITIALIZATION \n")
output_file.write(" // \n")
output_file.write(" // Initialise the contents of the instruction memory \n")
output_file.write(" //\n")
output_file.write(" // Intruction Set\n")
output_file.write(" // ==============\n")
for num, opcode in enumerate(instruction_set):
output_file.write(" // %s %s\n"%(num, opcode))
 
output_file.write(" //stage 1 opcode fetch\n")
output_file.write(" if (stage_1_enable) begin\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" register_1 <= registers[src_0];\n")
output_file.write(" registerb_1 <= registers[srcb_0];\n")
output_file.write(" dest_1 <= dest_0;\n")
output_file.write(" literal_1 <= literal_0;\n")
output_file.write(" opcode_1 <= opcode_0;\n")
output_file.write(" program_counter_1 <= program_counter_0;\n")
output_file.write(" end\n\n")
output_file.write(" // Intructions\n")
output_file.write(" // ===========\n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for location, instruction in enumerate(instruction_memory):
output_file.write(" instructions[%s] = {%s, %s, %s, %s};//%s\n"%(
location,
print_verilog_literal(opcode_bits, instruction["op"]),
print_verilog_literal(register_bits, instruction["dest"]),
print_verilog_literal(register_bits, instruction["src"]),
print_verilog_literal(32, instruction["srcb"] | instruction["literal"]),
instruction["comment"]))
output_file.write(" end\n\n")
 
output_file.write(" //stage 2 opcode fetch\n")
output_file.write(" if (stage_2_enable) begin\n")
output_file.write(" dest_2 <= dest_1;\n")
output_file.write(" case(opcode_1)\n\n")
if input_files or output_files:
 
#A frame is executed in each state
for opcode, instruction in enumerate(instruction_set):
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // OPEN FILES \n")
output_file.write(" // \n")
output_file.write(" // Open all files used at the start of the process \n")
 
if instruction["op"] == "literal":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= literal_1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for file_name, file_ in input_files.iteritems():
output_file.write(" %s = $fopenr(\"%s\");\n"%(file_, file_name))
for file_name, file_ in output_files.iteritems():
output_file.write(" %s = $fopen(\"%s\");\n"%(file_, file_name))
output_file.write(" end\n\n")
 
elif instruction["op"] == "move":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= register_1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // CPU IMPLEMENTAION OF C PROCESS \n")
output_file.write(" // \n")
output_file.write(" // This section of the file contains a CPU implementing the C process. \n")
 
elif instruction["op"] == "~":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= ~register_1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
 
elif instruction["op"] in binary_operators:
if memory_size_2:
output_file.write(" //implement memory for 2 byte x n arrays\n")
output_file.write(" if (memory_enable_2 == 1'b1) begin\n")
output_file.write(" memory_2[address_2] <= data_in_2;\n")
output_file.write(" end\n")
output_file.write(" data_out_2 <= memory_2[address_2];\n")
output_file.write(" memory_enable_2 <= 1'b0;\n\n")
 
if memory_size_4:
output_file.write(" //implement memory for 4 byte x n arrays\n")
output_file.write(" if (memory_enable_4 == 1'b1) begin\n")
output_file.write(" memory_4[address_4] <= data_in_4;\n")
output_file.write(" end\n")
output_file.write(" data_out_4 <= memory_4[address_4];\n")
output_file.write(" memory_enable_4 <= 1'b0;\n\n")
 
output_file.write(" write_enable_2 <= 0;\n")
 
if enable_divider:
output_file.write(" divider_go <= 0;\n")
if enable_multiplier:
output_file.write(" multiplier_go <= 0;\n")
if enable_adder:
output_file.write(" adder_go <= 0;\n")
if enable_int_to_float:
output_file.write(" int_to_float_go <= 0;\n")
if enable_float_to_int:
output_file.write(" float_to_int_go <= 0;\n")
 
output_file.write(" //stage 0 instruction fetch\n")
output_file.write(" if (stage_0_enable) begin\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" instruction_0 <= instructions[program_counter];\n")
output_file.write(" opcode_0 = instruction_0[%s:%s];\n"%(
register_bits * 2 + opcode_bits + 31,
register_bits * 2 + 32))
output_file.write(" dest_0 = instruction_0[%s:%s];\n"%(
register_bits * 2 + 31,
register_bits + 32))
output_file.write(" src_0 = instruction_0[%s:32];\n"%(
register_bits + 31))
output_file.write(" srcb_0 = instruction_0[%s:0];\n"%(register_bits-1))
output_file.write(" literal_0 = instruction_0[31:0];\n")
output_file.write(" if(write_enable_2) begin\n")
output_file.write(" registers[dest_2] <= result_2;\n")
output_file.write(" end\n")
output_file.write(" program_counter_0 <= program_counter;\n")
output_file.write(" program_counter <= program_counter + 1;\n")
output_file.write(" end\n\n")
 
output_file.write(" //stage 1 opcode fetch\n")
output_file.write(" if (stage_1_enable) begin\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" register_1 <= registers[src_0];\n")
output_file.write(" registerb_1 <= registers[srcb_0];\n")
output_file.write(" dest_1 <= dest_0;\n")
output_file.write(" literal_1 <= literal_0;\n")
output_file.write(" opcode_1 <= opcode_0;\n")
output_file.write(" program_counter_1 <= program_counter_0;\n")
output_file.write(" end\n\n")
 
output_file.write(" //stage 2 opcode fetch\n")
output_file.write(" if (stage_2_enable) begin\n")
output_file.write(" dest_2 <= dest_1;\n")
output_file.write(" case(opcode_1)\n\n")
 
#A frame is executed in each state
for opcode, instruction in enumerate(instruction_set):
 
if instruction["op"] == "literal":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= literal_1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "move":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= register_1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "~":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= ~register_1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "int_to_float":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" int_to <= register_1;\n")
output_file.write(" int_to_float_go <= 1;\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "float_to_int":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" float_to <= register_1;\n")
output_file.write(" float_to_int_go <= 1;\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] in binary_operators:
if instruction["literal"]:
if instruction["unsigned"]:
if instruction["float"]:
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
if instruction["op"] == "/":
if instruction["right"]:
output_file.write(" divider_a <= register_1;\n")
output_file.write(" divider_b <= literal_1;\n")
else:
output_file.write(" divider_a <= literal_1;\n")
output_file.write(" divider_b <= register_1;\n")
output_file.write(" divider_go <= 1;\n")
elif instruction["op"] == "*":
if instruction["right"]:
output_file.write(" multiplier_a <= register_1;\n")
output_file.write(" multiplier_b <= literal_1;\n")
else:
output_file.write(" multiplier_a <= literal_1;\n")
output_file.write(" multiplier_b <= register_1;\n")
output_file.write(" multiplier_go <= 1;\n")
elif instruction["op"] == "+":
if instruction["right"]:
output_file.write(" adder_a <= register_1;\n")
output_file.write(" adder_b <= literal_1;\n")
else:
output_file.write(" adder_a <= literal_1;\n")
output_file.write(" adder_b <= register_1;\n")
output_file.write(" adder_go <= 1;\n")
elif instruction["op"] == "-":
if instruction["right"]:
output_file.write(" adder_a <= register_1;\n")
output_file.write(" adder_b <= {~literal_1[31], literal_1[30:0]};\n")
else:
output_file.write(" adder_a <= literal_1;\n")
output_file.write(" adder_b <= {~register_1[31], register_1[30:0]};\n")
output_file.write(" adder_go <= 1;\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
elif instruction["unsigned"]:
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
if instruction["right"]:
output_file.write(" result_2 <= $unsigned(register_1) %s $unsigned(literal_1);\n"%(instruction["op"]))
else:
548,9 → 710,32
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
else:
if instruction["unsigned"]:
if instruction["float"]:
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
if instruction["op"] == "/":
output_file.write(" divider_a <= register_1;\n")
output_file.write(" divider_b <= registerb_1;\n")
output_file.write(" divider_go <= 1;\n")
elif instruction["op"] == "*":
output_file.write(" multiplier_a <= register_1;\n")
output_file.write(" multiplier_b <= registerb_1;\n")
output_file.write(" multiplier_go <= 1;\n")
elif instruction["op"] == "+":
output_file.write(" adder_a <= register_1;\n")
output_file.write(" adder_b <= registerb_1;\n")
output_file.write(" adder_go <= 1;\n")
elif instruction["op"] == "-":
output_file.write(" adder_a <= register_1;\n")
output_file.write(" adder_b <= {~registerb_1[31], registerb_1[30:0]};\n")
output_file.write(" adder_go <= 1;\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
elif instruction["unsigned"]:
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= $unsigned(register_1) %s $unsigned(registerb_1);\n"%(instruction["op"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
563,237 → 748,634
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "jmp_if_false":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" if (register_1 == 0) begin\n");
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
elif instruction["op"] == "jmp_if_false":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" if (register_1 == 0) begin\n");
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "jmp_if_true":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" if (register_1 != 0) begin\n");
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
elif instruction["op"] == "jmp_if_true":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" if (register_1 != 0) begin\n");
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "jmp_and_link":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" result_2 <= program_counter_1 + 1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "jmp_and_link":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" result_2 <= program_counter_1 + 1;\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "jmp_to_reg":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" program_counter <= register_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "jmp_to_reg":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" program_counter <= register_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "goto":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "goto":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" program_counter <= literal_1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "file_read":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" file_count = $fscanf(%s, \"%%d\\n\", result_2);\n"%(
input_files[instruction["file_"]]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "file_read":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" file_count = $fscanf(%s, \"%%d\\n\", result_2);\n"%(
input_files[instruction["file_name"]]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "file_write":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" $fdisplay(%s, \"%%d\", register_1);\n"%(
output_files[instruction["file_name"]]))
output_file.write(" end\n\n")
elif instruction["op"] == "file_write":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
if instruction["float"]:
output_file.write(' fp_value = (register_1[31]?-1.0:1.0) *\n')
output_file.write(' (2.0 ** (register_1[30:23]-127.0)) *\n')
output_file.write(' ({1\'d1, register_1[22:0]} / (2.0**23));\n')
output_file.write(' $fdisplay (%s, "%%f", fp_value);\n'%(
output_files[instruction["file_name"]]))
else:
output_file.write(" $fdisplay(%s, \"%%d\", register_1);\n"%(
output_files[instruction["file_name"]]))
output_file.write(" end\n\n")
 
elif instruction["op"] == "read":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" s_input_%s_ack <= 1'b1;\n"%instruction["input"])
output_file.write(" end\n\n")
elif instruction["op"] == "read":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" s_input_%s_ack <= 1'b1;\n"%instruction["input"])
output_file.write(" end\n\n")
 
elif instruction["op"] == "ready":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= 0;\n")
output_file.write(" result_2[0] <= input_%s_stb;\n"%(
instruction["input"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "ready":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= 0;\n")
output_file.write(" result_2[0] <= input_%s_stb;\n"%(
instruction["input"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "write":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" s_output_%s_stb <= 1'b1;\n"%instruction["output"])
output_file.write(" s_output_%s <= register_1;\n"%instruction["output"])
output_file.write(" end\n\n")
elif instruction["op"] == "write":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" s_output_%s_stb <= 1'b1;\n"%instruction["output"])
output_file.write(" s_output_%s <= register_1;\n"%instruction["output"])
output_file.write(" end\n\n")
 
elif instruction["op"] == "memory_read_request":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" address_%s <= register_1;\n"%(
instruction["element_size"]))
output_file.write(" end\n\n")
elif instruction["op"] == "memory_read_request":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" address_%s <= register_1;\n"%(
instruction["element_size"]))
output_file.write(" end\n\n")
 
elif instruction["op"] == "memory_read_wait":
pass
elif instruction["op"] == "memory_read_wait":
pass
 
elif instruction["op"] == "memory_read":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= data_out_%s;\n"%(
instruction["element_size"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "memory_read":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" result_2 <= data_out_%s;\n"%(
instruction["element_size"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "memory_write":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" address_%s <= register_1;\n"%(
instruction["element_size"]))
output_file.write(" data_in_%s <= registerb_1;\n"%(
instruction["element_size"]))
output_file.write(" memory_enable_%s <= 1'b1;\n"%(
instruction["element_size"]))
output_file.write(" end\n\n")
elif instruction["op"] == "memory_write":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" address_%s <= register_1;\n"%(
instruction["element_size"]))
output_file.write(" data_in_%s <= registerb_1;\n"%(
instruction["element_size"]))
output_file.write(" memory_enable_%s <= 1'b1;\n"%(
instruction["element_size"]))
output_file.write(" end\n\n")
 
elif instruction["op"] == "assert":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" if (register_1 == 0) begin\n")
output_file.write(" $display(\"Assertion failed at line: %s in file: %s\");\n"%(
instruction["line"],
instruction["file_"]))
output_file.write(" $finish_and_return(1);\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
elif instruction["op"] == "assert":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" if (register_1 == 0) begin\n")
output_file.write(" $display(\"Assertion failed at line: %s in file: %s\");\n"%(
instruction["line"],
instruction["file"]))
output_file.write(" $finish_and_return(1);\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "wait_clocks":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" timer <= register_1;\n")
output_file.write(" timer_enable <= 1;\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "wait_clocks":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
output_file.write(" timer <= register_1;\n")
output_file.write(" timer_enable <= 1;\n")
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "report":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
if instruction["unsigned"]:
output_file.write(' $display ("%%d (report at line: %s in file: %s)", $unsigned(register_1));\n'%(
instruction["line"],
instruction["file_"]))
else:
output_file.write(' $display ("%%d (report at line: %s in file: %s)", $signed(register_1));\n'%(
instruction["line"],
instruction["file_"],))
output_file.write(" end\n\n")
elif instruction["op"] == "report":
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
if instruction["float"]:
output_file.write(' fp_value = (register_1[31]?-1.0:1.0) *\n')
output_file.write(' (2.0 ** (register_1[30:23]-127.0)) *\n')
output_file.write(' ({1\'d1, register_1[22:0]} / (2.0**23));\n')
 
elif instruction["op"] == "stop":
#If we are in testbench mode stop the simulation
#If we are part of a larger design, other C programs may still be running
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
for file_ in input_files.values():
output_file.write(" $fclose(%s);\n"%file_)
for file_ in output_files.values():
output_file.write(" $fclose(%s);\n"%file_)
if testbench:
output_file.write(' $finish;\n')
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
output_file.write(' $display ("%%f (report at line: %s in file: %s)", fp_value);\n'%(
instruction["line"],
instruction["file"]))
 
elif instruction["unsigned"]:
 
output_file.write(" endcase\n")
output_file.write(" end\n")
output_file.write(' $display ("%%d (report at line: %s in file: %s)", $unsigned(register_1));\n'%(
instruction["line"],
instruction["file"]))
 
for instruction in instruction_set:
else:
 
if instruction["op"] == "read":
output_file.write(" if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%(
instruction["input"],
instruction["input"]))
output_file.write(" result_2 <= input_%s;\n"%(instruction["input"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" s_input_%s_ack <= 1'b0;\n"%instruction["input"])
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
output_file.write(' $display ("%%d (report at line: %s in file: %s)", $signed(register_1));\n'%(
instruction["line"],
instruction["file"],))
 
elif instruction["op"] == "write":
output_file.write(" if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%(
instruction["output"],
instruction["output"]))
output_file.write(" s_output_%s_stb <= 1'b0;\n"%instruction["output"])
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
output_file.write(" end\n\n")
 
output_file.write(" if (timer == 0) begin\n")
output_file.write(" if (timer_enable) begin\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" timer_enable <= 0;\n")
output_file.write(" end\n")
output_file.write(" end else begin\n")
output_file.write(" timer <= timer - 1;\n")
output_file.write(" end\n\n")
elif instruction["op"] == "stop":
#If we are in testbench mode stop the simulation
#If we are part of a larger design, other C programs may still be running
output_file.write(" 16'd%s:\n"%(opcode))
output_file.write(" begin\n")
for file_ in input_files.values():
output_file.write(" $fclose(%s);\n"%file_)
for file_ in output_files.values():
output_file.write(" $fclose(%s);\n"%file_)
if testbench:
output_file.write(' $finish;\n')
output_file.write(" stage_0_enable <= 0;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" end\n\n")
 
#Reset program counter and control signals
output_file.write(" if (rst == 1'b1) begin\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" timer <= 0;\n")
output_file.write(" timer_enable <= 0;\n")
output_file.write(" program_counter <= 0;\n")
for i in inputs:
output_file.write(" s_input_%s_ack <= 0;\n"%(i))
for i in outputs:
output_file.write(" s_output_%s_stb <= 0;\n"%(i))
output_file.write(" end\n")
output_file.write(" end\n")
for i in inputs:
output_file.write(" assign input_%s_ack = s_input_%s_ack;\n"%(i, i))
for i in outputs:
output_file.write(" assign output_%s_stb = s_output_%s_stb;\n"%(i, i))
output_file.write(" assign output_%s = s_output_%s;\n"%(i, i))
output_file.write("\nendmodule\n")
 
return inputs, outputs
output_file.write(" endcase\n")
output_file.write(" end\n")
 
for instruction in instruction_set:
 
if instruction["op"] == "read":
output_file.write(" if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%(
instruction["input"],
instruction["input"]))
output_file.write(" result_2 <= input_%s;\n"%(instruction["input"]))
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" s_input_%s_ack <= 1'b0;\n"%instruction["input"])
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
elif instruction["op"] == "write":
output_file.write(" if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%(
instruction["output"],
instruction["output"]))
output_file.write(" s_output_%s_stb <= 1'b0;\n"%instruction["output"])
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
output_file.write(" if (timer == 0) begin\n")
output_file.write(" if (timer_enable) begin\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" timer_enable <= 0;\n")
output_file.write(" end\n")
output_file.write(" end else begin\n")
output_file.write(" timer <= timer - 1;\n")
output_file.write(" end\n\n")
 
 
if enable_adder:
output_file.write(" if (adder_done) begin\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
if enable_multiplier:
output_file.write(" if (multiplier_done) begin\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
if enable_divider:
output_file.write(" if (divider_done) begin\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
if enable_int_to_float:
output_file.write(" if (int_to_float_done) begin\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
if enable_float_to_int:
output_file.write(" if (float_to_int_done) begin\n")
output_file.write(" write_enable_2 <= 1;\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 1;\n")
output_file.write(" stage_2_enable <= 1;\n")
output_file.write(" end\n\n")
 
#Reset program counter and control signals
output_file.write(" if (rst == 1'b1) begin\n")
output_file.write(" stage_0_enable <= 1;\n")
output_file.write(" stage_1_enable <= 0;\n")
output_file.write(" stage_2_enable <= 0;\n")
output_file.write(" timer <= 0;\n")
output_file.write(" timer_enable <= 0;\n")
output_file.write(" program_counter <= 0;\n")
for i in inputs:
output_file.write(" s_input_%s_ack <= 0;\n"%(i))
for i in outputs:
output_file.write(" s_output_%s_stb <= 0;\n"%(i))
output_file.write(" end\n")
output_file.write(" end\n")
for i in inputs:
output_file.write(" assign input_%s_ack = s_input_%s_ack;\n"%(i, i))
for i in outputs:
output_file.write(" assign output_%s_stb = s_output_%s_stb;\n"%(i, i))
output_file.write(" assign output_%s = s_output_%s;\n"%(i, i))
output_file.write("\nendmodule\n")
 
return inputs, outputs
 
def connect_float_to_int(output_file):
output_file.write(" \n float_to_int float_to_int_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(float_to),\n")
output_file.write(" .input_a_stb(float_to_stb),\n")
output_file.write(" .input_a_ack(float_to_ack),\n")
output_file.write(" .output_z(to_int),\n")
output_file.write(" .output_z_stb(to_int_stb),\n")
output_file.write(" .output_z_ack(to_int_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" float_to_int_done <= 0;\n")
output_file.write(" case(float_to_int_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (float_to_int_go) begin\n")
output_file.write(" float_to_int_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" float_to_stb <= 1;\n")
output_file.write(" if (float_to_stb && float_to_ack) begin\n")
output_file.write(" float_to_stb <= 0;\n")
output_file.write(" float_to_int_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" to_int_ack <= 1;\n")
output_file.write(" if (to_int_stb && to_int_ack) begin\n")
output_file.write(" to_int_ack <= 0;\n")
output_file.write(" result_2 <= to_int;\n")
output_file.write(" float_to_int_state <= wait_go;\n")
output_file.write(" float_to_int_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" float_to_int_state <= wait_go;\n")
output_file.write(" float_to_stb <= 0;\n")
output_file.write(" to_int_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def connect_int_to_float(output_file):
output_file.write(" \n int_to_float int_to_float_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(int_to),\n")
output_file.write(" .input_a_stb(int_to_stb),\n")
output_file.write(" .input_a_ack(int_to_ack),\n")
output_file.write(" .output_z(to_float),\n")
output_file.write(" .output_z_stb(to_float_stb),\n")
output_file.write(" .output_z_ack(to_float_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" int_to_float_done <= 0;\n")
output_file.write(" case(int_to_float_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (int_to_float_go) begin\n")
output_file.write(" int_to_float_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" int_to_stb <= 1;\n")
output_file.write(" if (int_to_stb && int_to_ack) begin\n")
output_file.write(" int_to_stb <= 0;\n")
output_file.write(" int_to_float_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" to_float_ack <= 1;\n")
output_file.write(" if (to_float_stb && to_float_ack) begin\n")
output_file.write(" to_float_ack <= 0;\n")
output_file.write(" result_2 <= to_float;\n")
output_file.write(" int_to_float_state <= wait_go;\n")
output_file.write(" int_to_float_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" int_to_float_state <= wait_go;\n")
output_file.write(" int_to_stb <= 0;\n")
output_file.write(" to_float_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def connect_divider(output_file):
output_file.write(" \n divider divider_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(divider_a),\n")
output_file.write(" .input_a_stb(divider_a_stb),\n")
output_file.write(" .input_a_ack(divider_a_ack),\n")
output_file.write(" .input_b(divider_b),\n")
output_file.write(" .input_b_stb(divider_b_stb),\n")
output_file.write(" .input_b_ack(divider_b_ack),\n")
output_file.write(" .output_z(divider_z),\n")
output_file.write(" .output_z_stb(divider_z_stb),\n")
output_file.write(" .output_z_ack(divider_z_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" divider_done <= 0;\n")
output_file.write(" case(div_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (divider_go) begin\n")
output_file.write(" div_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" divider_a_stb <= 1;\n")
output_file.write(" if (divider_a_stb && divider_a_ack) begin\n")
output_file.write(" divider_a_stb <= 0;\n")
output_file.write(" div_state <= write_b;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_b:\n")
output_file.write(" begin\n")
output_file.write(" divider_b_stb <= 1;\n")
output_file.write(" if (divider_b_stb && divider_b_ack) begin\n")
output_file.write(" divider_b_stb <= 0;\n")
output_file.write(" div_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" divider_z_ack <= 1;\n")
output_file.write(" if (divider_z_stb && divider_z_ack) begin\n")
output_file.write(" divider_z_ack <= 0;\n")
output_file.write(" result_2 <= divider_z;\n")
output_file.write(" div_state <= wait_go;\n")
output_file.write(" divider_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" div_state <= wait_go;\n")
output_file.write(" divider_a_stb <= 0;\n")
output_file.write(" divider_b_stb <= 0;\n")
output_file.write(" divider_z_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def connect_multiplier(output_file):
output_file.write(" \n multiplier multiplier_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(multiplier_a),\n")
output_file.write(" .input_a_stb(multiplier_a_stb),\n")
output_file.write(" .input_a_ack(multiplier_a_ack),\n")
output_file.write(" .input_b(multiplier_b),\n")
output_file.write(" .input_b_stb(multiplier_b_stb),\n")
output_file.write(" .input_b_ack(multiplier_b_ack),\n")
output_file.write(" .output_z(multiplier_z),\n")
output_file.write(" .output_z_stb(multiplier_z_stb),\n")
output_file.write(" .output_z_ack(multiplier_z_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" multiplier_done <= 0;\n")
output_file.write(" case(mul_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (multiplier_go) begin\n")
output_file.write(" mul_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" multiplier_a_stb <= 1;\n")
output_file.write(" if (multiplier_a_stb && multiplier_a_ack) begin\n")
output_file.write(" multiplier_a_stb <= 0;\n")
output_file.write(" mul_state <= write_b;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_b:\n")
output_file.write(" begin\n")
output_file.write(" multiplier_b_stb <= 1;\n")
output_file.write(" if (multiplier_b_stb && multiplier_b_ack) begin\n")
output_file.write(" multiplier_b_stb <= 0;\n")
output_file.write(" mul_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" multiplier_z_ack <= 1;\n")
output_file.write(" if (multiplier_z_stb && multiplier_z_ack) begin\n")
output_file.write(" multiplier_z_ack <= 0;\n")
output_file.write(" result_2 <= multiplier_z;\n")
output_file.write(" mul_state <= wait_go;\n")
output_file.write(" multiplier_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" endcase\n\n")
output_file.write(" if (rst) begin\n")
output_file.write(" mul_state <= wait_go;\n")
output_file.write(" multiplier_a_stb <= 0;\n")
output_file.write(" multiplier_b_stb <= 0;\n")
output_file.write(" multiplier_z_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def connect_adder(output_file):
output_file.write(" \n adder adder_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(adder_a),\n")
output_file.write(" .input_a_stb(adder_a_stb),\n")
output_file.write(" .input_a_ack(adder_a_ack),\n")
output_file.write(" .input_b(adder_b),\n")
output_file.write(" .input_b_stb(adder_b_stb),\n")
output_file.write(" .input_b_ack(adder_b_ack),\n")
output_file.write(" .output_z(adder_z),\n")
output_file.write(" .output_z_stb(adder_z_stb),\n")
output_file.write(" .output_z_ack(adder_z_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" adder_done <= 0;\n")
output_file.write(" case(add_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (adder_go) begin\n")
output_file.write(" add_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" adder_a_stb <= 1;\n")
output_file.write(" if (adder_a_stb && adder_a_ack) begin\n")
output_file.write(" adder_a_stb <= 0;\n")
output_file.write(" add_state <= write_b;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_b:\n")
output_file.write(" begin\n")
output_file.write(" adder_b_stb <= 1;\n")
output_file.write(" if (adder_b_stb && adder_b_ack) begin\n")
output_file.write(" adder_b_stb <= 0;\n")
output_file.write(" add_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" adder_z_ack <= 1;\n")
output_file.write(" if (adder_z_stb && adder_z_ack) begin\n")
output_file.write(" adder_z_ack <= 0;\n")
output_file.write(" result_2 <= adder_z;\n")
output_file.write(" add_state <= wait_go;\n")
output_file.write(" adder_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" add_state <= wait_go;\n")
output_file.write(" adder_a_stb <= 0;\n")
output_file.write(" adder_b_stb <= 0;\n")
output_file.write(" adder_z_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def generate_float_to_int_signals(output_file):
output_file.write(" reg [31:0] float_to;\n")
output_file.write(" reg float_to_stb;\n")
output_file.write(" wire float_to_ack;\n")
output_file.write(" wire [31:0] to_int;\n")
output_file.write(" wire to_int_stb;\n")
output_file.write(" reg to_int_ack;\n")
output_file.write(" reg [1:0] float_to_int_state;\n")
output_file.write(" reg float_to_int_go;\n")
output_file.write(" reg float_to_int_done;\n")
 
def generate_int_to_float_signals(output_file):
output_file.write(" reg [31:0] int_to;\n")
output_file.write(" reg int_to_stb;\n")
output_file.write(" wire int_to_ack;\n")
output_file.write(" wire [31:0] to_float;\n")
output_file.write(" wire to_float_stb;\n")
output_file.write(" reg to_float_ack;\n")
output_file.write(" reg [1:0] int_to_float_state;\n")
output_file.write(" reg int_to_float_go;\n")
output_file.write(" reg int_to_float_done;\n")
 
def generate_divider_signals(output_file):
output_file.write(" reg [31:0] divider_a;\n")
output_file.write(" reg divider_a_stb;\n")
output_file.write(" wire divider_a_ack;\n")
output_file.write(" reg [31:0] divider_b;\n")
output_file.write(" reg divider_b_stb;\n")
output_file.write(" wire divider_b_ack;\n")
output_file.write(" wire [31:0] divider_z;\n")
output_file.write(" wire divider_z_stb;\n")
output_file.write(" reg divider_z_ack;\n")
output_file.write(" reg [1:0] div_state;\n")
output_file.write(" reg divider_go;\n")
output_file.write(" reg divider_done;\n")
 
def generate_multiplier_signals(output_file):
output_file.write(" reg [31:0] multiplier_a;\n")
output_file.write(" reg multiplier_a_stb;\n")
output_file.write(" wire multiplier_a_ack;\n")
output_file.write(" reg [31:0] multiplier_b;\n")
output_file.write(" reg multiplier_b_stb;\n")
output_file.write(" wire multiplier_b_ack;\n")
output_file.write(" wire [31:0] multiplier_z;\n")
output_file.write(" wire multiplier_z_stb;\n")
output_file.write(" reg multiplier_z_ack;\n")
output_file.write(" reg [1:0] mul_state;\n")
output_file.write(" reg multiplier_go;\n")
output_file.write(" reg multiplier_done;\n")
 
def generate_adder_signals(output_file):
output_file.write(" reg [31:0] adder_a;\n")
output_file.write(" reg adder_a_stb;\n")
output_file.write(" wire adder_a_ack;\n")
output_file.write(" reg [31:0] adder_b;\n")
output_file.write(" reg adder_b_stb;\n")
output_file.write(" wire adder_b_ack;\n")
output_file.write(" wire [31:0] adder_z;\n")
output_file.write(" wire adder_z_stb;\n")
output_file.write(" reg adder_z_ack;\n")
output_file.write(" reg [1:0] add_state;\n")
output_file.write(" reg adder_go;\n")
output_file.write(" reg adder_done;\n")
/chips/compiler/allocator.py
4,44 → 4,45
 
class Allocator:
 
"""Maintain a pool of registers, variables and arrays. Keep track of what they are used for."""
"""Maintain a pool of registers, variables and arrays. Keep track of what they are used for."""
 
def __init__(self, reuse):
self.registers = []
self.all_registers = {}
self.memory_size_2 = 0
self.memory_size_4 = 0
self.reuse = reuse
self.memory_content_2 = {}
self.memory_content_4 = {}
def __init__(self, reuse):
self.registers = []
self.all_registers = {}
self.memory_size_2 = 0
self.memory_size_4 = 0
self.reuse = reuse
self.memory_content_2 = {}
self.memory_content_4 = {}
 
def new_array(self, size, contents, element_size):
if element_size == 2:
reg = self.memory_size_2
self.memory_size_2 += int(size)
if contents is not None:
for location, value in enumerate(contents, reg):
self.memory_content_2[location] = value
return reg
elif element_size == 4:
reg = self.memory_size_4
self.memory_size_4 += int(size)
if contents is not None:
for location, value in enumerate(contents, reg):
self.memory_content_4[location] = value
return reg
def new_array(self, size, contents, element_size):
if element_size == 2:
reg = self.memory_size_2
self.memory_size_2 += int(size)
if contents is not None:
for location, value in enumerate(contents, reg):
self.memory_content_2[location] = value
return reg
elif element_size == 4:
reg = self.memory_size_4
self.memory_size_4 += int(size)
if contents is not None:
for location, value in enumerate(contents, reg):
self.memory_content_4[location] = value
return reg
 
def regsize(self, reg):
return self.all_registers[reg][1]
 
def new(self, size, name="temporary_register"):
assert type(size) == int
reg = 0
while reg in self.registers or (reg in self.all_registers and self.regsize(reg) != size):
reg += 1
self.registers.append(reg)
self.all_registers[reg] = (name, size)
return reg
 
def new(self, size, name="temporary_register"):
assert type(size) == int
reg = 0
while reg in self.registers:
reg += 1
self.registers.append(reg)
self.all_registers[reg] = (name, size)
return reg
 
def free(self, register):
if register in self.registers and self.reuse:
self.registers.remove(register)
def free(self, register):
if register in self.registers and self.reuse:
self.registers.remove(register)
/chips/compiler/optimizer.py
4,36 → 4,36
 
def cleanup_functions(instructions):
 
"""Remove functions that are not called"""
"""Remove functions that are not called"""
 
 
#This is an iterative processr. Once a function is removed,
#there may be more unused functions
while 1:
#This is an iterative processr. Once a function is removed,
#there may be more unused functions
while 1:
 
#find function calls
live_functions = {}
for instruction in instructions:
if instruction["op"] == "jmp_and_link":
if instruction["label"].startswith("function"):
live_functions[instruction["label"]] = None
#find function calls
live_functions = {}
for instruction in instructions:
if instruction["op"] == "jmp_and_link":
if instruction["label"].startswith("function"):
live_functions[instruction["label"]] = None
 
#remove instructions without function calls
kept_instructions = []
generate_on = True
for instruction in instructions:
if instruction["op"] == "label":
if instruction["label"].startswith("function"):
if instruction["label"] in live_functions:
generate_on = True
else:
generate_on = False
if generate_on:
kept_instructions.append(instruction)
#remove instructions without function calls
kept_instructions = []
generate_on = True
for instruction in instructions:
if instruction["op"] == "label":
if instruction["label"].startswith("function"):
if instruction["label"] in live_functions:
generate_on = True
else:
generate_on = False
if generate_on:
kept_instructions.append(instruction)
 
if len(instructions) == len(kept_instructions):
return kept_instructions
instructions = kept_instructions
if len(instructions) == len(kept_instructions):
return kept_instructions
instructions = kept_instructions
 
def reallocate_registers(instructions, registers):
 
41,9 → 41,9
new_registers = {}
n = 0
for register, definition in registers.iteritems():
register_map[register] = n
new_registers[n] = definition
n+=1
register_map[register] = n
new_registers[n] = definition
n+=1
 
for instruction in instructions:
if "dest" in instruction:
84,116 → 84,119
 
def parallelise(instructions):
 
def modifies_register(instruction):
def modifies_register(instruction):
 
"""Return the register modified by this instruction if any"""
"""Return the register modified by this instruction if any"""
 
if "dest" in instruction:
return instruction["dest"]
return None
if "dest" in instruction:
return instruction["dest"]
return None
 
def uses_registers(instruction):
def uses_registers(instruction):
 
"""Return the registers used by this instruction if any"""
"""Return the registers used by this instruction if any"""
 
registers = []
for field in ["src", "srcb"]:
if field in instruction:
registers.append(instruction[field])
return registers
registers = []
for field in ["src", "srcb"]:
if field in instruction:
registers.append(instruction[field])
return registers
 
def memory_clash(a, b):
def memory_clash(a, b):
 
"""do instructions result in a memory clash"""
"""do instructions result in a memory clash"""
 
if a["op"] in ["memory_write", "memory_write_literal"]:
return b["op"] in ["memory_write", "memory_write_literal", "memory_read", "memory_read_wait", "memory_read_request"]
if a["op"] in ["memory_write", "memory_write_literal"]:
return b["op"] in ["memory_write", "memory_write_literal", "memory_read", "memory_read_wait", "memory_read_request"]
 
if b["op"] in ["memory_write", "memory_write_literal"]:
return a["op"] in ["memory_write", "memory_write_literal", "memory_read", "memory_read_wait", "memory_read_request"]
if b["op"] in ["memory_write", "memory_write_literal"]:
return a["op"] in ["memory_write", "memory_write_literal", "memory_read", "memory_read_wait", "memory_read_request"]
 
if a["op"] in ["memory_read", "memory_read_wait", "memory_read_request", "memory_write", "memory_write_literal"]:
return b["op"] == a["op"]
if a["op"] in ["memory_read", "memory_read_wait", "memory_read_request", "memory_write", "memory_write_literal"]:
return b["op"] == a["op"]
 
if b["op"] in ["memory_read", "memory_read_wait", "memory_read_request", "memory_write", "memory_write_literal"]:
return b["op"] == a["op"]
if b["op"] in ["memory_read", "memory_read_wait", "memory_read_request", "memory_write", "memory_write_literal"]:
return b["op"] == a["op"]
 
def is_part_of_read(a, b):
def is_part_of_read(a, b):
 
"""requests, waits and reads with the same sequence number must not be concurrent"""
"""requests, waits and reads with the same sequence number must not be concurrent"""
 
read_instructions = ["memory_read_request", "memory_read_wait", "memory_read"]
if (a["op"] in read_instructions) and (b["op"] in read_instructions):
return a["sequence"] == b["sequence"]
return False
read_instructions = ["memory_read_request", "memory_read_wait", "memory_read"]
if (a["op"] in read_instructions) and (b["op"] in read_instructions):
return a["sequence"] == b["sequence"]
return False
 
def is_solitary(instruction):
def is_solitary(instruction):
 
"""Return True if an instruction cannot be executed in parallel with other instructions"""
"""Return True if an instruction cannot be executed in parallel with other instructions"""
 
return instruction["op"] in ["read", "write", "ready", "label", "/", "%"]
if "type" in instruction and instruction["type"] == "float":
if instruction["op"] in ["+", "-", "/", "*"]:
return True
return instruction["op"] in ["read", "write", "ready", "label", "/", "%", "int_to_float", "float_to_int", "file_write", "file_read"]
 
def is_jump(instruction):
def is_jump(instruction):
 
"""Return True if an instruction contains a branch or jump"""
"""Return True if an instruction contains a branch or jump"""
 
return instruction["op"] in ["goto", "jmp_if_true", "jmp_if_false", "jmp_and_link",
"jmp_to_reg"]
return instruction["op"] in ["goto", "jmp_if_true", "jmp_if_false", "jmp_and_link",
"jmp_to_reg"]
 
def is_dependent(instruction, frame, preceding):
def is_dependent(instruction, frame, preceding):
 
"""determine whether an instruction is dependent on the outcome of:
- an instruction within the current frame
- preceding instructions not within the frame """
"""determine whether an instruction is dependent on the outcome of:
- an instruction within the current frame
- preceding instructions not within the frame """
 
for i in frame + preceding:
if modifies_register(i) is not None:
if modifies_register(i) in uses_registers(instruction):
return True
if modifies_register(i) == modifies_register(instruction):
return True
if memory_clash(i, instruction):
return True
if is_part_of_read(i, instruction):
return True
if is_jump(i):
return True
for i in preceding:
if modifies_register(instruction) is not None:
if modifies_register(instruction) in uses_registers(i):
return True
if memory_clash(i, instruction):
return True
if is_part_of_read(i, instruction):
return True
if is_jump(instruction) and preceding:
return True
return False
for i in frame + preceding:
if modifies_register(i) is not None:
if modifies_register(i) in uses_registers(instruction):
return True
if modifies_register(i) == modifies_register(instruction):
return True
if memory_clash(i, instruction):
return True
if is_part_of_read(i, instruction):
return True
if is_jump(i):
return True
for i in preceding:
if modifies_register(instruction) is not None:
if modifies_register(instruction) in uses_registers(i):
return True
if memory_clash(i, instruction):
return True
if is_part_of_read(i, instruction):
return True
if is_jump(instruction) and preceding:
return True
return False
 
def add_instructions(frame, instructions):
def add_instructions(frame, instructions):
 
"""Add more instructions to the current frame if dependencies allow."""
"""Add more instructions to the current frame if dependencies allow."""
 
instructions_added = True
while instructions_added:
instructions_added = False
for index, instruction in enumerate(instructions):
if is_solitary(instruction):
return
for i in frame:
if is_jump(i):
return
if is_solitary(i):
return
if not is_dependent(instruction, frame, instructions[:index]):
frame.append(instructions.pop(index))
instructions_added = True
break
instructions_added = True
while instructions_added:
instructions_added = False
for index, instruction in enumerate(instructions):
if is_solitary(instruction):
return
for i in frame:
if is_jump(i):
return
if is_solitary(i):
return
if not is_dependent(instruction, frame, instructions[:index]):
frame.append(instructions.pop(index))
instructions_added = True
break
 
frames = []
while instructions:
frame = [instructions.pop(0)]
add_instructions(frame, instructions)
frames.append(frame)
frames = []
while instructions:
frame = [instructions.pop(0)]
add_instructions(frame, instructions)
frames.append(frame)
 
return frames
return frames
/chips/compiler/tokens.py
7,42 → 7,43
 
from chips.compiler.exceptions import C2CHIPError
from chips.compiler.builtins import builtins
from chips.compiler.library import libs
 
operators = [
"!", "~", "+", "-", "*", "/", "//", "%", "=", "==", "<", ">", "<=", ">=",
"!=", "|", "&", "^", "||", "&&", "(", ")", "{", "}", "[", "]", ";", "<<",
">>", ",", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=", "++",
"--", "?", ":", "."
"!=", "|", "&", "^", "||", "&&", "(", ")", "{", "}", "[", "]", ";", "<<",
">>", ",", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=", "^=",
"++", "--", "?", ":", "."
]
 
class Tokens:
 
"""Break the input file into a stream of tokens,
"""Break the input file into a stream of tokens,
provide functions to traverse the stream."""
 
def __init__(self, filename):
self.tokens = []
self.filename = None
self.lineno = None
self.scan("built in", StringIO.StringIO(builtins))
self.scan(filename)
self.tokens = []
self.filename = None
self.lineno = None
self.scan("built in", StringIO.StringIO(builtins))
self.scan(filename)
 
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)
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"):
51,20 → 52,25
self.tokens.extend(tokens)
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)
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
continue
 
newline = True
for char in line:
 
if not token:
token = char
 
#c style comment
elif (token + char).startswith("/*"):
if (token + char).endswith("*/"):
71,7 → 77,7
token = ""
else:
token += char
 
#c++ style comment
elif token.startswith("//"):
if newline:
78,7 → 84,7
token = char
else:
token += char
 
#identifier
elif token[0].isalpha():
if char.isalnum() or char== "_":
86,10 → 92,10
else:
tokens.append((self.filename, self.lineno, token))
token = char
 
#number
elif token[0].isdigit():
if char.upper() in "UXABCDEFL0123456789":
if char.upper() in "UXABCDEFL0123456789.":
token += char
else:
tokens.append((self.filename, self.lineno, token))
116,7 → 122,7
token = ""
else:
token += char
 
#operator
elif token in operators:
if token + char in operators:
124,51 → 130,51
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 peek(self):
 
"""Return the next token in the stream, but don't consume it"""
 
if self.tokens:
return self.tokens[0][2]
else:
return ""
 
def get(self):
 
"""Return the next token in the stream, and consume it"""
 
if self.tokens:
self.lineno = self.tokens[0][1]
self.filename = self.tokens[0][0]
filename, lineno, token = self.tokens.pop(0)
return token
 
def end(self):
 
"""Return True if all the tokens have been consumed"""
 
return not self.tokens
 
def expect(self, expected):
"""Consume the next token in the stream,
 
"""Consume the next token in the stream,
generate an error if it is not as expected."""
 
filename, lineno, actual = self.tokens.pop(0)
if self.tokens:
self.lineno = self.tokens[0][1]
/chips/compiler/library.py
0,0 → 1,101
#!/usr/bin/env python
"""Support Library for builtin Functionality"""
 
__author__ = "Jon Dawson"
__copyright__ = "Copyright (C) 2013, Jonathan P Dawson"
__version__ = "0.1"
 
libs={"print.h":"""
 
//Print a string *string* to stdout
void print_string(unsigned string[]){
unsigned i=0;
while(string[i]){
stdout_put_char(string[i]);
i++;
}
}
 
//Print an unsigned int to stdout in hex format
void print_uhex(unsigned uhex){
unsigned digit_3 = (uhex >> 12) & 0xf;
unsigned digit_2 = (uhex >> 8) & 0xf;
unsigned digit_1 = (uhex >> 4) & 0xf;
unsigned digit_0 = uhex & 0xf;
if(digit_3 < 9) stdout_put_char(digit_3 | 0x30);
else stdout_put_char(digit_3 + 87);
if(digit_2 < 9) stdout_put_char(digit_2 | 0x30);
else stdout_put_char(digit_2 + 87);
if(digit_1 < 9) stdout_put_char(digit_1 | 0x30);
else stdout_put_char(digit_1 + 87);
if(digit_0 < 9) stdout_put_char(digit_0 | 0x30);
else stdout_put_char(digit_0 + 87);
}
 
//Print an unsigned int to stdout in decimal format
//leading 0s will be suppressed
void print_udecimal(unsigned udecimal){
unsigned digit;
unsigned significant = 0;
digit = 0;
while(udecimal >= 10000){
udecimal -= 10000;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
digit = 0;
while(udecimal >= 1000){
udecimal -= 1000;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
digit = 0;
while(udecimal >= 100){
udecimal -= 100;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
digit = 0;
while(udecimal >= 10){
udecimal -= 10;
digit += 1;
}
if(digit | significant){
stdout_put_char(digit | 0x30);
significant = 1;
}
stdout_put_char(udecimal | 0x30);
}
 
//Print a signed int to stdout in hex format
void print_hex(int hex){
if(hex >= 0){
print_uhex(hex);
} else {
stdout_put_char('-');
print_uhex(-hex);
}
}
 
//Print a signed int to stdout in decimal format
//leading 0s will be suppressed
void print_decimal(int decimal){
if(decimal >= 0){
print_udecimal(decimal);
} else {
stdout_put_char('-');
print_udecimal(-decimal);
}
}
 
 
"""}
chips/compiler/library.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: chips/compiler/parser.py,cover =================================================================== --- chips/compiler/parser.py,cover (revision 3) +++ chips/compiler/parser.py,cover (revision 4) @@ -2,28 +2,22 @@ > __copyright__ = "Copyright (C) 2012, Jonathan P Dawson" > __version__ = "0.1" +> import struct +> from copy import copy + > from parse_tree import * > from tokens import Tokens > from allocator import Allocator -> def optimise_if(if_statement): -> try: -> if value(if_statement.expression): -> return if_statement.true_statement -> elif if_statement.false_statement: -> return if_statement.false_statement -> else: -> null_instruction = Block() -> null_instruction.statements = [] -> return null_instruction -> except NotConstant: -> return if_statement +> types = ["float", "signed", "unsigned", "short", "long", "char", "int", "void"] +> numeric_types = ["float", "signed", "unsigned", "short", "long", "char", "int"] +> storage_specifiers = ["const"] > class Parser: > """Turn the C input file into a tree of expressions and statements.""" -> def __init__(self, input_file, reuse): +> def __init__(self, input_file, reuse, initialize_memory): > self.scope = {} > self.function = None > self.loop = None @@ -30,6 +24,7 @@ > self.tokens = Tokens(input_file) > self.allocator = Allocator(reuse) > self.structs = [] +> self.initialize_memory = initialize_memory > def parse_process(self): > process = Process() @@ -47,43 +42,138 @@ > process.main = self.main > return process +> def parse_type_specifier(self): +> type_specifiers = [] + +> while self.tokens.peek() in types + self.structs + storage_specifiers: +> type_specifiers.append(self.tokens.get()) + +> signed = True +> if "unsigned" in type_specifiers: +> signed = False +> if "signed" in type_specifiers: +! self.tokens.error("Cannot be signed and unsigned") + +> size = 2 +> if "long" in type_specifiers: +> if "short" in type_specifiers: +! self.tokens.error("Cannot be long and short") +> size = 4 + +> type_ = "int" +> for i in type_specifiers: +> if i in self.structs: +> type_ = i +> size = 2 +> signed = False + +> if "float" in type_specifiers: +> if "short" in type_specifiers: +! self.tokens.error("Float cannot be short") +> if "long" in type_specifiers: +! self.tokens.error("Float cannot be long (but double can)") +> if "unsigned" in type_specifiers: +! self.tokens.error("Float cannot be unsigned") +> type_ = "float" +> size = 4 +> signed = True + +> const = False +> if "const" in type_specifiers: +> const = True + +> if "void" in type_specifiers: +> type_ = "void" +> size = 2 +> signed = False + + +> return type_, size, signed, const + +> def parse_argument(self): +> type_, size, signed, const = self.parse_type_specifier() + +> if type_ in ["void"]: +! self.tokens.error("argument cannot be void") +> else: +> argument = self.tokens.get() +> if type_ in self.structs: +> declaration = self.scope[type_] +> else: +> if self.tokens.peek() == "[": +> self.tokens.expect("[") +> self.tokens.expect("]") +> declaration = ArrayDeclaration( +> self.allocator, +> 2, +> type_+"[]", +> type_, +> size, +> signed, +> None, +> self.initialize_memory) +> else: +> declaration = VariableDeclaration( +> self.allocator, +> None, +> argument, +> type_, +> size, +> signed, +> const) +> instance = declaration.instance() +> self.scope[argument] = instance +> return instance.reference() + > def parse_function(self): > function = Function() > function.allocator = self.allocator -> stored_scope = self.scope -> type_ = self.tokens.get() +> stored_scope = copy(self.scope) +> type_, size, signed, const = self.parse_type_specifier() > name = self.tokens.get() - + #check if it is a global declaration > if self.tokens.peek() != "(": -> if type_ not in ["int", "short", "long", "char"] + self.structs: -! self.tokens.error("unknown type") -> return self.parse_global_declaration(type_, name) +> return self.parse_global_declaration(type_, size, signed, const, name) #otherwise continue parsing a function > self.tokens.expect("(") > function.name = name > function.type_ = type_ -> function.return_address = self.allocator.new(function.name+" return address") -> if type_ not in ["int", "short", "long", "char", "void"]: -! self.tokens.error("unknown type") +> function.size = size +> function.signed = signed + +> function.return_address = self.allocator.new(2, +> function.name+" return address") + > if type_ != "void": -> function.return_value = self.allocator.new(function.name+" return value") + +> if type_ in self.structs: +! declaration = self.scope[type_] +> else: +> if self.tokens.peek() == "[": +! self.tokens.error( +! "Functions cannot return arrays") +> else: +> declaration = VariableDeclaration( +> self.allocator, +> None, +> function.name+" return value", +> type_, +> size, +> signed, +> const) + +> function.return_value = declaration.instance().reference() + > function.arguments = [] > while self.tokens.peek() != ")": -> type_ = self.tokens.get() -> if type_ not in ["int", "short", "long", "char"]: -! self.tokens.error("unknown type") -> argument = self.tokens.get() -> if self.tokens.peek() == "[": -> self.tokens.expect("[") -> self.tokens.expect("]") -> type_+="[]" -> function.arguments.append(Argument(argument, type_, self)) +> function.arguments.append(self.parse_argument()) > if self.tokens.peek() == ",": > self.tokens.expect(",") > else: > break + > self.tokens.expect(")") > self.function = function > function.statement = self.parse_statement() @@ -113,6 +203,7 @@ > def parse_return(self): > return_ = Return() > return_.function = self.function +> return_.allocator = self.allocator > self.function.return_statement = return_ > self.tokens.expect("return") > if hasattr(self.function, "return_value"): @@ -156,7 +247,7 @@ > return wait_clocks > def parse_statement(self): -> if self.tokens.peek() in ["int", "short", "long", "char"] + self.structs: +> if self.tokens.peek() in numeric_types + self.structs + storage_specifiers: > return self.parse_compound_declaration() > elif self.tokens.peek() == "struct": > return self.parse_struct_declaration() @@ -196,41 +287,40 @@ > def parse_assignment(self): > assignment_operators = [ -> "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=", -> "++", "--" +> "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "<<=", ">>=" > ] > lvalue = self.parse_ternary_expression() > if self.tokens.peek() in assignment_operators: -> if not hasattr(lvalue, "declaration"): +> if lvalue.const(): + > self.tokens.error( -> "left hand operand of assignment is not modifiable" -> ) +> "left hand operand of assignment is not modifiable") + > operator = self.tokens.get() > if operator == "=": > expression = self.parse_ternary_expression() -> elif operator in ["++", "--"]: -> expression = Binary( -> operator[:-1], -> lvalue, -> Constant(1), -> self.allocator -> ) > else: -> expression = Binary( -> operator[:-1], -> lvalue, -> self.parse_ternary_expression(), -> self.allocator -> ) -> if lvalue.type_ != expression.type_: -> self.tokens.error( -> "type mismatch in assignment" -> ) + +> expression = self.parse_ternary_expression() +> left = lvalue +> left, expression = self.coerce_types(left, expression) +> expression = Binary(operator[:-1], left, expression) + +> if expression.type_() != lvalue.type_(): +> if expression.type_() == "int" and lvalue.type_() == "float": +! expression = IntToFloat(expression) +> elif expression.type_() == "float" and lvalue.type_() == "int": +> expression = FloatToInt(expression) +> else: +> self.tokens.error( +> "type mismatch in assignment expected: %s actual: %s"%( +> lvalue.type_(), +> expression.type_())) + > return Assignment(lvalue, expression, self.allocator) > else: > return lvalue - > def parse_if(self): > if_ = If() > if_.allocator = self.allocator @@ -237,10 +327,9 @@ > self.tokens.expect("if") > self.tokens.expect("(") > if_.expression = self.parse_expression() -> if if_.expression.type_ not in ["int", "short", "long", "char"]: +> if if_.expression.type_() not in ["unsigned", "int", "short", "long", "char"]: > self.tokens.error( -> "if statement conditional must be an integer like expression" -> ) +> "if statement conditional must be an integer like expression") > self.tokens.expect(")") > if_.true_statement = self.parse_statement() > if self.tokens.peek() == "else": @@ -248,7 +337,7 @@ > if_.false_statement = self.parse_statement() > else: > if_.false_statement = None -> return optimise_if(if_) +> return if_ > def parse_switch(self): > switch = Switch() @@ -256,10 +345,9 @@ > self.tokens.expect("switch") > self.tokens.expect("(") > expression = self.parse_expression() -> if expression.type_ not in ["int", "short", "long", "char"]: +> if expression.type_() not in ["unsigned", "int", "short", "long", "char"]: > self.tokens.error( -> "switch statement expression must be an integer like expression" -> ) +> "switch statement expression must be an integer like expression") > self.tokens.expect(")") > stored_loop = self.loop > self.loop = switch @@ -273,21 +361,19 @@ > def parse_case(self): > self.tokens.expect("case") > expression = self.parse_expression() -> if expression.type_ not in ["int", "short", "long", "char"]: +> if expression.type_() not in ["int"]: > self.tokens.error( -> "case expression must be an integer like expression" -> ) +> "case expression must be an integer like expression") > self.tokens.expect(":") > try: -> expression = value(expression) +> expression = expression.value() > case = Case() -> self.loop.cases[expression] = case +> self.loop.cases[expression] = case > except NotConstant: > self.tokens.error("case expression must be constant") > except AttributeError: > self.tokens.error( -> "case statements may only be use inside a switch statment" -> ) +> "case statements may only be use inside a switch statment") > return case > def parse_default(self): @@ -296,12 +382,10 @@ > default = Default() > if not hasattr(self.loop, "cases"): > self.tokens.error( -> "default statements may only be used inside a switch statment" -> ) +> "default statements may only be used inside a switch statment") > if hasattr(self.loop, "default"): > self.tokens.error( -> "A switch statement may only have one default statement" -> ) +> "A switch statement may only have one default statement") > self.loop.default=default > return default @@ -317,18 +401,17 @@ > self.loop = stored_loop > if_ = If() +> loop.statement = if_ > break_ = Break() > break_.loop = loop > if_.allocator = self.allocator -> if expression.type_ not in ["int", "short", "long", "char"]: +> if expression.type_() not in ["int"]: > self.tokens.error( -> "if statement conditional must be an integer like expression" -> ) +> "while statement conditional must be an integer like expression") > if_.expression = expression > if_.false_statement = break_ > if_.true_statement = statement -> loop.statement = optimise_if(if_) > return loop > def parse_for(self): @@ -341,10 +424,16 @@ > self.tokens.expect(";") > if self.tokens.peek() != ";": > for_.expression = self.parse_expression() -> if for_.expression.type_ not in ["int", "short", "long", "char"]: +> if for_.expression.type_() not in [ +> "unsigned", +> "int", +> "short", +> "long", +> "char"]: + > self.tokens.error( -> "for statement conditional must be an integer like expression" -> ) +> "For statement conditional must be an integer like expression") + > self.tokens.expect(";") > if self.tokens.peek() != ")": > for_.statement2 = self.parse_discard() @@ -357,7 +446,7 @@ > def parse_block(self): > block = Block() -> stored_scope = self.scope +> stored_scope = copy(self.scope) > self.tokens.expect("{") > block.statements = [] > while self.tokens.peek() != "}": @@ -370,9 +459,16 @@ > self.tokens.expect("{") > members = {} > while self.tokens.peek() != "}": -> type_ = self.tokens.get() +> type_, size, signed, const = self.parse_type_specifier() > name = self.tokens.get() -> members[name] = self.parse_declaration(type_, name) + +> members[name] = self.parse_declaration( +> type_, +> size, +> signed, +> const, +> name) + > self.tokens.expect(";") > self.tokens.expect("}") > return members @@ -402,10 +498,17 @@ > self.scope[name] = instance > return instance -> def parse_global_declaration(self, type_, name): +> def parse_global_declaration(self, type_, size, signed, const, name): > instances = [] > while True: -> instance = self.parse_declaration(type_, name).instance() + +> instance = self.parse_declaration( +> type_, +> size, +> signed, +> const, +> name).instance() + > self.scope[name] = instance > instances.append(instance) > if self.tokens.peek() == ",": @@ -417,11 +520,18 @@ > return CompoundDeclaration(instances) > def parse_compound_declaration(self): -> type_ = self.tokens.get() +> type_, size, signed, const = self.parse_type_specifier() > instances = [] > while True: > name = self.tokens.get() -> instance = self.parse_declaration(type_, name).instance() + +> instance = self.parse_declaration( +> type_, +> size, +> signed, +> const, +> name).instance() + > self.scope[name] = instance > instances.append(instance) > if self.tokens.peek() == ",": @@ -432,41 +542,75 @@ > self.tokens.expect(";") > return CompoundDeclaration(instances) -> def parse_declaration(self, type_, name): +> def parse_declaration(self, type_, size, signed, const, name): #struct declaration > if type_ in self.structs: > declaration = self.scope[type_] -> elif type_ in ["int", "short", "long", "char"]: - #array declaration +> elif type_ in ["int", "float"]: + #array declaration > if self.tokens.peek() == "[": -> size = None +> array_size = None > self.tokens.expect("[") > if self.tokens.peek() != "]": -> size = self.tokens.get() +> size_expression = self.parse_ternary_expression() +> if size_expression.type_() != "int": +! self.tokens.error("Array size must be an integer like expression") +> try: +> array_size = size_expression.value() +> except NotConstant: +> self.tokens.error("Array size must be constant") + > self.tokens.expect("]") > initializer = None > if self.tokens.peek() == "=": > self.tokens.expect("=") > initializer = self.tokens.get() -> initializer = [ord(i) for i in initializer.strip('"')] + [0] -> size = len(initializer) -> if size is None: -> self.tokens.error("array size must be specified if not initialized") -> type_+="[]" -> declaration = ArrayDeclaration(self.allocator, size, type_, initializer) +> initializer = [ord(i) for i in initializer.strip('"').decode("string_escape")] + [0] +> array_size = len(initializer) +> if array_size is None: - #simple variable declaration +> self.tokens.error( +> "array size must be specified if not initialized") + +> array_type=type_+"[]" +> initialize_memory = self.initialize_memory +> declaration = ArrayDeclaration( +> self.allocator, +> array_size, +> array_type, +> type_, +> size, +> signed, +> initializer, +> self.initialize_memory) + + #simple variable declaration > else: > if self.tokens.peek() == "=": > self.tokens.expect("=") > initializer = self.parse_ternary_expression() > else: -> initializer = Constant(0) +> initializer = Constant(0, type_, size, signed) + +> if type_ != initializer.type_(): + +> if type_ == "int" and initializer.type_() == "float": +> initializer = FloatToInt(initializer) +> elif type_ == "float" and initializer.type_() == "int": +> initializer = IntToFloat(initializer) +> else: +> self.tokens.error( +> "type mismatch in intializer expected: %s actual: %s"%( +> type_, +> intitializer.type_())) > declaration = VariableDeclaration( -> self.allocator, -> initializer, +> self.allocator, +> initializer, > name, -> type_ +> type_, +> size, +> signed, +> const > ) > return declaration @@ -499,6 +643,65 @@ > expression = AND(expression, self.parse_binary_expression(["|"])) > return expression +> def substitute_function(self, binary_expression): + +> """ +> For some operations are more easily implemented in sofftware. +> This function substitutes a call to the builtin library function. +> """ + +> functions = { +> "False,int,int,4,/" : "long_unsigned_divide_xxxx", +> "True,int,int,4,/" : "long_divide_xxxx", +> "False,int,int,2,/" : "unsigned_divide_xxxx", +> "True,int,int,2,/" : "divide_xxxx", +> "False,int,int,4,%" : "long_unsigned_modulo_xxxx", +> "True,int,int,4,%" : "long_modulo_xxxx", +> "False,int,int,2,%" : "unsigned_modulo_xxxx", +> "True,int,int,2,%" : "modulo_xxxx", +> "True,float,float,4,==" : "float_equal_xxxx", +> "True,float,float,4,!=" : "float_ne_xxxx", +> "True,float,float,4,<" : "float_lt_xxxx", +> "True,float,float,4,>" : "float_gt_xxxx", +> "True,float,float,4,<=" : "float_le_xxxx", +> "True,float,float,4,>=" : "float_ge_xxxx", +> } + + #select a function that matches the template. +> signature = ",".join([ +> str(binary_expression.signed()), +> binary_expression.left.type_(), +> binary_expression.right.type_(), +> str(binary_expression.size()), +> binary_expression.operator]) + + #Some things can't be implemented in verilog, substitute them with a function +> if signature in functions: +> function = self.scope[functions[signature]] +> function_call = FunctionCall(function) +> function_call.arguments = [binary_expression.left, binary_expression.right] +> return function_call +> else: +> return binary_expression + +> def coerce_types(self, left, right): + +> """ +> Convert numeric types in expressions. +> """ + +> if left.type_() != right.type_(): +> if left.type_() == "float" and right.type_() == "int": +> return left, IntToFloat(right) +> elif left.type_() == "int" and right.type_() == "float": +> return IntToFloat(left), right +> else: +> self.tokens.error("Incompatible types : %s %s"%( +> left.type_(), +> right.type_())) + +> return left, right + > def parse_binary_expression(self, operators): > operator_precedence = { > "|": ["^"], @@ -510,43 +713,60 @@ > "+": ["*", "/", "%"], > } > if operators[0] not in operator_precedence: -> expression = self.parse_unary_expression() +> left = self.parse_unary_expression() > while self.tokens.peek() in operators: -> expression = Binary( -> self.tokens.get(), -> expression, -> self.parse_unary_expression(), -> self.allocator -> ) -> return expression +> operator = self.tokens.get() +> right = self.parse_unary_expression() +> left, right = self.coerce_types(left, right) +> left = Binary(operator, left, right) +> left = self.substitute_function(left) +> return left > else: > next_operators = operator_precedence[operators[0]] -> expression = self.parse_binary_expression(next_operators) +> left = self.parse_binary_expression(next_operators) > while self.tokens.peek() in operators: -> expression = Binary( -> self.tokens.get(), -> expression, -> self.parse_binary_expression(next_operators), -> self.allocator -> ) -> return expression +> operator = self.tokens.get() +> right = self.parse_binary_expression(next_operators) +> left, right = self.coerce_types(left, right) +> left = Binary(operator, left, right) +> left = self.substitute_function(left) +> return left > def parse_unary_expression(self): > if self.tokens.peek() == "!": > operator = self.tokens.get() -> expression = self.parse_paren_expression() -> return Binary("==", expression, Constant(0), self.allocator) +> expression = self.parse_postfix_expression() +> return Binary("==", expression, Constant(0)) > elif self.tokens.peek() == "-": > operator = self.tokens.get() -> expression = self.parse_paren_expression() -> return Binary("-", Constant(0), expression, self.allocator) +> expression = self.parse_postfix_expression() +> return Binary("-", Constant(0, +> expression.type_(), +> expression.size(), +> expression.signed()), +> expression) > elif self.tokens.peek() == "~": > operator = self.tokens.get() -> expression = self.parse_paren_expression() +> expression = self.parse_postfix_expression() > return Unary("~", expression) +> elif self.tokens.peek() == "sizeof": +> operator = self.tokens.get() +> expression = self.parse_unary_expression() +> return SizeOf(expression) > else: -> return self.parse_paren_expression() +> return self.parse_postfix_expression() +> def parse_postfix_expression(self): +> expression = self.parse_paren_expression() +> while self.tokens.peek() in ["++", "--"]: +> operator = self.tokens.get() +> expression = PostIncrement( +> operator[:-1], +> expression, +> self.allocator +> ) +> return expression + > def parse_paren_expression(self): > if self.tokens.peek() == "(": > self.tokens.expect("(") @@ -566,6 +786,22 @@ > else: > return self.parse_number() +> def parse_file_read(self): +! self.tokens.expect("(") +! file_name = self.tokens.get() +> file_name = file_name.strip('"').decode("string_escape") +> self.tokens.expect(")") +! return FileRead(file_name) + +> def parse_file_write(self): +> self.tokens.expect("(") +> expression = self.parse_expression() +> self.tokens.expect(",") +> file_name = self.tokens.get() +> file_name = file_name.strip('"').decode("string_escape") +> self.tokens.expect(")") +> return FileWrite(file_name, expression) + > def parse_input(self, name): > input_name = name.replace("input_", "") > self.tokens.expect("(") @@ -592,7 +828,14 @@ > return self.parse_ready(name) > if name.startswith("output_"): > return self.parse_output(name) -> function_call = FunctionCall() +> if name == "file_read": +> return self.parse_file_read() +> if name == "file_write": +> return self.parse_file_write() +> if name not in self.scope: +> self.tokens.error("Unknown function: %s"%name) +> function = self.scope[name] +> function_call = FunctionCall(function) > function_call.arguments = [] > self.tokens.expect("(") > while self.tokens.peek() != ")": @@ -603,11 +846,7 @@ > break > self.tokens.expect(")") -> if name not in self.scope: -> self.tokens.error("Unknown function: %s"%name) -> function_call.function = self.scope[name] -> function_call.type_ = function_call.function.type_ > required_arguments = len(function_call.function.arguments) > actual_arguments = len(function_call.arguments) > if required_arguments != actual_arguments: @@ -614,22 +853,31 @@ > self.tokens.error("Function %s takes %s arguments %s given."%( > name, > len(function_call.function.arguments), -> len(function_call.arguments) -> )) +> len(function_call.arguments))) > required_arguments = function_call.function.arguments > actual_arguments = function_call.arguments +> corrected_arguments = [] > for required, actual in zip(required_arguments, actual_arguments): -> if required.type_ != actual.type_: -> self.tokens.error("Type mismatch expected type : %s got: %s."%( -> required.type_, -> actual.type_ -> )) +> if not compatible(required, actual): +> if actual.type_() == "int" and required.type_() == "float": +> actual = IntToFloat(actual) +> elif actual.type_() == "float" and required.type_() == "int": +! actual = FloatToInt(actual) +> else: +> self.tokens.error( +> "type mismatch in assignment expected: %s actual: %s"%( +> required.type_(), +> actual.type_())) +> corrected_arguments.append(actual) +> function_call.arguments = corrected_arguments - > return function_call > def parse_number(self): > token = self.tokens.get() +> type_ = "int" +> size = 2 +> signed = True > if token.startswith("'"): > try: > token = eval(token) @@ -636,36 +884,102 @@ > value = ord(token) ! except SyntaxError: ! self.tokens.error("%s is not a character literal"%token) +> elif token.startswith('"'): +> try: +> initializer = [ord(i) for i in token.strip('"').decode("string_escape")] + [0] +> size = len(initializer) +> initialize_memory = self.initialize_memory +> declaration = ArrayDeclaration( +> self.allocator, +> size, +> "int[]", +> "int", +> 2, +> False, +> initializer, +> self.initialize_memory) +> return ConstArray(declaration.instance()) +! except SyntaxError: +! self.tokens.error("%s is not a character literal"%token) +> elif "." in token: + #float literal +> try: +> type_ = "float" +> signed = True +> size = 4 +> token = token.upper().replace("F", "") +> token = token.upper().replace("L", "") +> value = float(eval(token)) + +> try: +> byte_value = struct.pack(">f", value) +> except OverflowError: +> self.tokens.error("value too large") + +> except SyntaxError: +> self.tokens.error("%s is not a floating point literal"%token) > else: + #integer literal > try: +> if "U" in token.upper(): +> signed = False +> if "L" in token.upper(): +> size = 4 +> token = token.upper().replace("U", "") > value = int(eval(token)) + +> if signed: +> if value > 2**((size * 8)-1) - 1: +> self.tokens.error("value too large") +> if value < -(2**((size * 8)-1)): +> self.tokens.error("value too small") +> else: +> if value > 2**(size * 8) - 1: +! self.tokens.error("value too large") +> if value < 0: +> self.tokens.error("value too small") + > except SyntaxError: > self.tokens.error("%s is not an integer literal"%token) -> return Constant(value) +> return Constant(value, type_, size, signed) + > def parse_variable(self, name): > if name not in self.scope: > self.tokens.error("Unknown variable: %s"%name) > instance = self.scope[name] > return self.parse_variable_array_struct(instance) - + > def parse_variable_array_struct(self, instance): -> if instance.type_ in ["int", "short", "long", "char"]: -> return Variable(instance, self.allocator) -> elif instance.type_.endswith("[]"): +> if instance.type_() in numeric_types: + +> if not hasattr(instance, "reference"): + +> self.tokens.error( +> "Not an expression") + +> return Variable(instance) +> elif instance.type_().endswith("[]"): > if self.tokens.peek() == "[": > self.tokens.expect("[") > index_expression = self.parse_expression() > self.tokens.expect("]") -> if index_expression.type_ not in ["int", "short", "long", "char"]: +> if index_expression.type_() not in ["int"]: + > self.tokens.error( -> "array indices must be an integer like expression" -> ) -> return ArrayIndex(instance, index_expression, self.allocator) +> "Array indices must be an integer like expression") + +> return ArrayIndex(instance, index_expression) > else: -> return Array(instance, self.allocator) -> elif instance.type_ == "struct": -> self.tokens.expect(".") -> member = self.tokens.get() -> instance = instance.members[member] -> return self.parse_variable_array_struct(instance) +> return Array(instance) +> elif instance.type_().startswith("struct"): +> if self.tokens.peek() == ".": +> self.tokens.expect(".") +> member = self.tokens.get() +> instance = instance.members[member] +> return self.parse_variable_array_struct(instance) +> else: +> return Struct(instance) + +> def compatible(left, right): +> return left.type_() == right.type_()
/chips/compiler/verilog_speed.py
5,530 → 5,1145
__copyright__ = "Copyright (C) 2013, Jonathan P Dawson"
__version__ = "0.1"
 
import fpu
 
def unique(l):
 
"""In the absence of set in older python implementations, make list values unique"""
"""In the absence of set in older python implementations, make list values unique"""
 
return dict(zip(l, l)).keys()
return dict(zip(l, l)).keys()
 
def log2(frames):
 
"""Integer only algorithm to calculate the number of bits needed to store a number"""
"""Integer only algorithm to calculate the number of bits needed to store a number"""
 
bits = 1
power = 2
while power < frames:
bits += 1
power *= 2
return bits
bits = 1
power = 2
while power < frames:
bits += 1
power *= 2
return bits
 
def to_gray(i):
 
"""Convert integer to gray code"""
"""Convert integer to gray code"""
 
return (i >> 1) ^ i
return (i >> 1) ^ i
 
def generate_CHIP(input_file,
name,
frames,
output_file,
registers,
memory_size_2,
memory_size_4,
def sign_extend(value, bytes_):
bits = bytes_*8
mask = (1<<bits)-1
mask = ~mask
if value & 1<<(bits-1):
return value | mask
else:
return value
 
 
def floating_point_enables(frames):
enable_adder = False
enable_multiplier = False
enable_divider = False
enable_int_to_float = False
enable_float_to_int = False
for frame in frames:
for i in frame:
if i["op"] == "+" and "type" in i and i["type"] == "float":
enable_adder = True
if i["op"] == "-" and "type" in i and i["type"] == "float":
enable_adder = True
if i["op"] == "*" and "type" in i and i["type"] == "float":
enable_multiplier = True
if i["op"] == "/" and "type" in i and i["type"] == "float":
enable_divider = True
if i["op"] == "int_to_float":
enable_int_to_float = True
if i["op"] == "float_to_int":
enable_float_to_int = True
return (
enable_adder,
enable_multiplier,
enable_divider,
enable_int_to_float,
enable_float_to_int)
 
 
def generate_CHIP(input_file,
name,
frames,
output_file,
registers,
memory_size_2,
memory_size_4,
initialize_memory,
memory_content_2,
memory_content_4,
memory_content_2,
memory_content_4,
no_tb_mode=False):
 
"""A big ugly function to crunch through all the instructions and generate the CHIP equivilent"""
"""A big ugly function to crunch through all the instructions and generate the CHIP equivilent"""
 
#calculate the values of jump locations
location = 0
labels = {}
new_frames = []
for frame in frames:
if frame[0]["op"] == "label":
labels[frame[0]["label"]] = location
#calculate the values of jump locations
location = 0
labels = {}
new_frames = []
for frame in frames:
if frame[0]["op"] == "label":
labels[frame[0]["label"]] = location
else:
new_frames.append(frame)
location += 1
frames = new_frames
 
#substitue real values for labeled jump locations
for frame in frames:
for instruction in frame:
if "label" in instruction:
instruction["label"]=labels[instruction["label"]]
 
#list all inputs and outputs used in the program
inputs = unique([i["input"] for frame in frames for i in frame if "input" in i])
outputs = unique([i["output"] for frame in frames for i in frame if "output" in i])
input_files = unique([i["file_name"] for frame in frames for i in frame if "file_read" == i["op"]])
output_files = unique([i["file_name"] for frame in frames for i in frame if "file_write" == i["op"]])
testbench = not inputs and not outputs and not no_tb_mode
enable_adder, enable_multiplier, enable_divider, enable_int_to_float, enable_float_to_int = floating_point_enables(frames)
 
#Do not generate a port in testbench mode
inports = [
("input_" + i, 16) for i in inputs
] + [
("input_" + i + "_stb", 1) for i in inputs
] + [
("output_" + i + "_ack", 1) for i in outputs
]
 
outports = [
("output_" + i, 16) for i in outputs
] + [
("output_" + i + "_stb", 1) for i in outputs
] + [
("input_" + i + "_ack", 1) for i in inputs
]
 
#create list of signals
signals = [
("timer", 16),
("program_counter", log2(len(frames))),
("address_2", 16),
("data_out_2", 16),
("data_in_2", 16),
("write_enable_2", 1),
("address_4", 16),
("data_out_4", 32),
("data_in_4", 32),
("write_enable_4", 1),
] + [
("register_%s"%(register), definition[1]*8) for register, definition in registers.iteritems()
] + [
("s_output_" + i + "_stb", 16) for i in outputs
] + [
("s_output_" + i, 16) for i in outputs
] + [
("s_input_" + i + "_ack", 16) for i in inputs
]
 
if testbench:
signals.append(("clk", 1))
signals.append(("rst", 1))
else:
new_frames.append(frame)
location += 1
frames = new_frames
inports.append(("clk", 1))
inports.append(("rst", 1))
 
#substitue real values for labeled jump locations
for frame in frames:
for instruction in frame:
if "label" in instruction:
instruction["label"]=labels[instruction["label"]]
if enable_adder:
output_file.write(fpu.adder)
if enable_divider:
output_file.write(fpu.divider)
if enable_multiplier:
output_file.write(fpu.multiplier)
if enable_int_to_float:
output_file.write(fpu.int_to_float)
if enable_float_to_int:
output_file.write(fpu.float_to_int)
 
#list all inputs and outputs used in the program
inputs = unique([i["input"] for frame in frames for i in frame if "input" in i])
outputs = unique([i["output"] for frame in frames for i in frame if "output" in i])
input_files = unique([i["file_name"] for frame in frames for i in frame if "file_read" == i["op"]])
output_files = unique([i["file_name"] for frame in frames for i in frame if "file_write" == i["op"]])
testbench = not inputs and not outputs and not no_tb_mode
#output the code in verilog
output_file.write("//name : %s\n"%name)
output_file.write("//tag : c components\n")
for i in inputs:
output_file.write("//input : input_%s:16\n"%i)
for i in outputs:
output_file.write("//output : output_%s:16\n"%i)
output_file.write("//source_file : %s\n"%input_file)
output_file.write("///%s\n"%"".join(["=" for i in name]))
output_file.write("///\n")
output_file.write("///*Created by C2CHIP*\n\n")
 
#Do not generate a port in testbench mode
inports = [
("input_" + i, 16) for i in inputs
] + [
("input_" + i + "_stb", 1) for i in inputs
] + [
("output_" + i + "_ack", 1) for i in outputs
]
 
outports = [
("output_" + i, 16) for i in outputs
] + [
("output_" + i + "_stb", 1) for i in outputs
] + [
("input_" + i + "_ack", 1) for i in inputs
]
output_file.write("// Register Allocation\n")
output_file.write("// ===================\n")
output_file.write("// %s %s %s \n"%("Register".center(20), "Name".center(20), "Size".center(20)))
for register, definition in registers.iteritems():
register_name, size = definition
output_file.write("// %s %s %s \n"%(str(register).center(20), register_name.center(20), str(size).center(20)))
 
#create list of signals
signals = [
("timer", 16),
("program_counter", log2(len(frames))),
("address_2", 16),
("data_out_2", 16),
("data_in_2", 16),
("write_enable_2", 1),
("address_4", 16),
("data_out_4", 32),
("data_in_4", 32),
("write_enable_4", 1),
] + [
("register_%s"%(register), definition[1]*8) for register, definition in registers.iteritems()
] + [
("s_output_" + i + "_stb", 16) for i in outputs
] + [
("s_output_" + i, 16) for i in outputs
] + [
("s_input_" + i + "_ack", 16) for i in inputs
]
output_file.write(" \n`timescale 1ns/1ps\n")
output_file.write("module %s"%name)
 
if testbench:
signals.append(("clk", 1))
signals.append(("rst", 1))
else:
inports.append(("clk", 1))
inports.append(("rst", 1))
all_ports = [name for name, size in inports + outports]
if all_ports:
output_file.write("(")
output_file.write(",".join(all_ports))
output_file.write(");\n")
else:
output_file.write(";\n")
 
#output the code in verilog
output_file.write("//name : %s\n"%name)
output_file.write("//tag : c components\n")
for i in inputs:
output_file.write("//input : input_%s:16\n"%i)
for i in outputs:
output_file.write("//output : output_%s:16\n"%i)
output_file.write("//source_file : %s\n"%input_file)
output_file.write("///%s\n"%"".join(["=" for i in name]))
output_file.write("///\n")
output_file.write("///*Created by C2CHIP*\n\n")
output_file.write(" integer file_count;\n")
 
if enable_adder:
generate_adder_signals(output_file)
if enable_multiplier:
generate_multiplier_signals(output_file)
if enable_divider:
generate_divider_signals(output_file)
if enable_int_to_float:
generate_int_to_float_signals(output_file)
if enable_float_to_int:
generate_float_to_int_signals(output_file)
output_file.write(" real fp_value;\n")
 
output_file.write("// Register Allocation\n")
output_file.write("// ===================\n")
output_file.write("// %s %s %s \n"%("Register".center(20), "Name".center(20), "Size".center(20)))
for register, definition in registers.iteritems():
register_name, size = definition
output_file.write("// %s %s %s \n"%(str(register).center(20), register_name.center(20), str(size).center(20)))
if enable_adder or enable_multiplier or enable_divider or enable_int_to_float or enable_float_to_int:
output_file.write(" parameter wait_go = 3'd0,\n")
output_file.write(" write_a = 3'd1,\n")
output_file.write(" write_b = 3'd2,\n")
output_file.write(" read_z = 3'd3,\n")
output_file.write(" wait_next = 3'd4;\n")
 
output_file.write(" \n`timescale 1ns/1ps\n")
output_file.write("module %s"%name)
input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)]))
for i in input_files.values():
output_file.write(" integer %s;\n"%i)
 
all_ports = [name for name, size in inports + outports]
if all_ports:
output_file.write("(")
output_file.write(",".join(all_ports))
output_file.write(");\n")
else:
output_file.write(";\n")
output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)]))
for i in output_files.values():
output_file.write(" integer %s;\n"%i)
 
output_file.write(" integer file_count;\n")
def write_declaration(object_type, name, size, value=None):
if size == 1:
output_file.write(object_type)
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
else:
output_file.write(object_type)
output_file.write("[%i:0]"%(size-1))
output_file.write(" ")
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
 
input_files = dict(zip(input_files, ["input_file_%s"%i for i, j in enumerate(input_files)]))
for i in input_files.values():
output_file.write(" integer %s;\n"%i)
for name, size in inports:
write_declaration(" input ", name, size)
 
output_files = dict(zip(output_files, ["output_file_%s"%i for i, j in enumerate(output_files)]))
for i in output_files.values():
output_file.write(" integer %s;\n"%i)
for name, size in outports:
write_declaration(" output ", name, size)
 
for name, size in signals:
write_declaration(" reg ", name, size)
 
def write_declaration(object_type, name, size, value=None):
if size == 1:
output_file.write(object_type)
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
else:
output_file.write(object_type)
output_file.write("[%i:0]"%(size-1))
output_file.write(" ")
output_file.write(name)
if value is not None:
output_file.write("= %s'd%s"%(size,value))
output_file.write(";\n")
memory_size_2 = int(memory_size_2)
memory_size_4 = int(memory_size_4)
if memory_size_2:
output_file.write(" reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1))
if memory_size_4:
output_file.write(" reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1))
 
for name, size in inports:
write_declaration(" input ", name, size)
#generate clock and reset in testbench mode
if testbench:
 
for name, size in outports:
write_declaration(" output ", name, size)
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // CLOCK AND RESET GENERATION \n")
output_file.write(" // \n")
output_file.write(" // This file was generated in test bench mode. In this mode, the verilog \n")
output_file.write(" // output file can be executed directly within a verilog simulator. \n")
output_file.write(" // In test bench mode, a simulated clock and reset signal are generated within\n")
output_file.write(" // the output file. \n")
output_file.write(" // Verilog files generated in testbecnch mode are not suitable for synthesis, \n")
output_file.write(" // or for instantiation within a larger design.\n")
 
for name, size in signals:
write_declaration(" reg ", name, size)
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" rst <= 1'b1;\n")
output_file.write(" #50 rst <= 1'b0;\n")
output_file.write(" end\n\n")
 
memory_size_2 = int(memory_size_2)
memory_size_4 = int(memory_size_4)
if memory_size_2:
output_file.write(" reg [15:0] memory_2 [%i:0];\n"%(memory_size_2-1))
if memory_size_4:
output_file.write(" reg [31:0] memory_4 [%i:0];\n"%(memory_size_4-1))
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" clk <= 1'b0;\n")
output_file.write(" while (1) begin\n")
output_file.write(" #5 clk <= ~clk;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
#generate clock and reset in testbench mode
if testbench:
#Instance Floating Point Arithmetic
if enable_adder or enable_multiplier or enable_divider or enable_int_to_float or enable_float_to_int:
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // CLOCK AND RESET GENERATION \n")
output_file.write(" // \n")
output_file.write(" // This file was generated in test bench mode. In this mode, the verilog \n")
output_file.write(" // output file can be executed directly within a verilog simulator. \n")
output_file.write(" // In test bench mode, a simulated clock and reset signal are generated within\n")
output_file.write(" // the output file. \n")
output_file.write(" // Verilog files generated in testbecnch mode are not suitable for synthesis, \n")
output_file.write(" // or for instantiation within a larger design.\n")
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // Floating Point Arithmetic \n")
output_file.write(" // \n")
output_file.write(" // Generate IEEE 754 single precision divider, adder and multiplier \n")
output_file.write(" // \n")
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" rst <= 1'b1;\n")
output_file.write(" #50 rst <= 1'b0;\n")
output_file.write(" end\n\n")
if enable_divider:
connect_divider(output_file)
if enable_multiplier:
connect_multiplier(output_file)
if enable_adder:
connect_adder(output_file)
if enable_int_to_float:
connect_int_to_float(output_file)
if enable_float_to_int:
connect_float_to_int(output_file)
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
output_file.write(" clk <= 1'b0;\n")
output_file.write(" while (1) begin\n")
output_file.write(" #5 clk <= ~clk;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
#Generate a state machine to execute the instructions
binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=",
"<=", "==", "!="]
 
#Generate a state machine to execute the instructions
binary_operators = ["+", "-", "*", "/", "|", "&", "^", "<<", ">>", "<",">", ">=",
"<=", "==", "!="]
 
if initialize_memory and (memory_content_2 or memory_content_4):
 
if initialize_memory and (memory_content_2 or memory_content_4):
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // MEMORY INITIALIZATION \n")
output_file.write(" // \n")
output_file.write(" // In order to reduce program size, array contents have been stored into \n")
output_file.write(" // memory at initialization. In an FPGA, this will result in the memory being \n")
output_file.write(" // initialized when the FPGA configures. \n")
output_file.write(" // Memory will not be re-initialized at reset. \n")
output_file.write(" // Dissable this behaviour using the no_initialize_memory switch \n")
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // MEMORY INITIALIZATION \n")
output_file.write(" // \n")
output_file.write(" // In order to reduce program size, array contents have been stored into \n")
output_file.write(" // memory at initialization. In an FPGA, this will result in the memory being \n")
output_file.write(" // initialized when the FPGA configures. \n")
output_file.write(" // Memory will not be re-initialized at reset. \n")
output_file.write(" // Dissable this behaviour using the no_initialize_memory switch \n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for location, content in memory_content_2.iteritems():
output_file.write(" memory_2[%s] = %s;\n"%(location, content))
for location, content in memory_content_4.iteritems():
output_file.write(" memory_4[%s] = %s;\n"%(location, content))
output_file.write(" end\n\n")
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for location, content in memory_content_2.iteritems():
output_file.write(" memory_2[%s] = %s;\n"%(location, content))
for location, content in memory_content_4.iteritems():
output_file.write(" memory_4[%s] = %s;\n"%(location, content))
output_file.write(" end\n\n")
if input_files or output_files:
 
if input_files or output_files:
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // OPEN FILES \n")
output_file.write(" // \n")
output_file.write(" // Open all files used at the start of the process \n")
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // OPEN FILES \n")
output_file.write(" // \n")
output_file.write(" // Open all files used at the start of the process \n")
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for file_name, file_ in input_files.iteritems():
output_file.write(" %s = $fopenr(\"%s\");\n"%(file_, file_name))
for file_name, file_ in output_files.iteritems():
output_file.write(" %s = $fopen(\"%s\");\n"%(file_, file_name))
output_file.write(" end\n\n")
 
output_file.write(" \n initial\n")
output_file.write(" begin\n")
for file_name, file_ in input_files.iteritems():
output_file.write(" %s = $fopenr(\"%s\");\n"%(file_, file_name))
for file_name, file_ in output_files.iteritems():
output_file.write(" %s = $fopen(\"%s\");\n"%(file_, file_name))
output_file.write(" end\n\n")
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // FSM IMPLEMENTAION OF C PROCESS \n")
output_file.write(" // \n")
output_file.write(" // This section of the file contains a Finite State Machine (FSM) implementing\n")
output_file.write(" // the C process. In general execution is sequential, but the compiler will \n")
output_file.write(" // attempt to execute instructions in parallel if the instruction dependencies\n")
output_file.write(" // allow. Further concurrency can be achieved by executing multiple C \n")
output_file.write(" // processes concurrently within the device. \n")
 
output_file.write("\n //////////////////////////////////////////////////////////////////////////////\n")
output_file.write(" // FSM IMPLEMENTAION OF C PROCESS \n")
output_file.write(" // \n")
output_file.write(" // This section of the file contains a Finite State Machine (FSM) implementing\n")
output_file.write(" // the C process. In general execution is sequential, but the compiler will \n")
output_file.write(" // attempt to execute instructions in parallel if the instruction dependencies\n")
output_file.write(" // allow. Further concurrency can be achieved by executing multiple C \n")
output_file.write(" // processes concurrently within the device. \n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
 
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
if memory_size_2:
output_file.write(" //implement memory for 2 byte x n arrays\n")
output_file.write(" if (write_enable_2 == 1'b1) begin\n")
output_file.write(" memory_2[address_2] <= data_in_2;\n")
output_file.write(" end\n")
output_file.write(" data_out_2 <= memory_2[address_2];\n")
output_file.write(" write_enable_2 <= 1'b0;\n\n")
 
if memory_size_2:
output_file.write(" //implement memory for 2 byte x n arrays\n")
output_file.write(" if (write_enable_2 == 1'b1) begin\n")
output_file.write(" memory_2[address_2] <= data_in_2;\n")
output_file.write(" end\n")
output_file.write(" data_out_2 <= memory_2[address_2];\n")
output_file.write(" write_enable_2 <= 1'b0;\n\n")
if memory_size_4:
output_file.write(" //implement memory for 4 byte x n arrays\n")
output_file.write(" if (write_enable_4 == 1'b1) begin\n")
output_file.write(" memory_4[address_4] <= data_in_4;\n")
output_file.write(" end\n")
output_file.write(" data_out_4 <= memory_4[address_4];\n")
output_file.write(" write_enable_4 <= 1'b0;\n\n")
 
if memory_size_4:
output_file.write(" //implement memory for 4 byte x n arrays\n")
output_file.write(" if (write_enable_4 == 1'b1) begin\n")
output_file.write(" memory_4[address_4] <= data_in_4;\n")
output_file.write(" end\n")
output_file.write(" data_out_4 <= memory_4[address_4];\n")
output_file.write(" write_enable_4 <= 1'b0;\n\n")
output_file.write(" //implement timer\n")
output_file.write(" timer <= 16'h0000;\n\n")
output_file.write(" case(program_counter)\n\n")
 
output_file.write(" //implement timer\n")
output_file.write(" timer <= 16'h0000;\n\n")
output_file.write(" case(program_counter)\n\n")
#A frame is executed in each state
for location, frame in enumerate(frames):
output_file.write(" 16'd%s:\n"%to_gray(location))
output_file.write(" begin\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
for instruction in frame:
 
#A frame is executed in each state
for location, frame in enumerate(frames):
output_file.write(" 16'd%s:\n"%to_gray(location))
output_file.write(" begin\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
for instruction in frame:
if instruction["op"] == "literal":
output_file.write(
" register_%s <= %s;\n"%(
instruction["dest"],
instruction["literal"]))
 
if instruction["op"] == "literal":
output_file.write(
" register_%s <= %s;\n"%(
instruction["dest"],
instruction["literal"]))
elif instruction["op"] == "move":
output_file.write(
" register_%s <= register_%s;\n"%(
instruction["dest"],
instruction["src"]))
 
elif instruction["op"] == "move":
output_file.write(
" register_%s <= register_%s;\n"%(
instruction["dest"],
instruction["src"]))
elif instruction["op"] in ["~"]:
output_file.write(
" register_%s <= ~register_%s;\n"%(
instruction["dest"],
instruction["src"]))
 
elif instruction["op"] in ["~"]:
output_file.write(
" register_%s <= ~register_%s;\n"%(
instruction["dest"],
instruction["src"]))
elif instruction["op"] in ["int_to_float"]:
output_file.write(" int_to <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= to_float;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" int_to_float_go <= 1;\n")
output_file.write(" if (int_to_float_done) begin\n")
output_file.write(" int_to_float_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
 
elif instruction["op"] in binary_operators and "left" in instruction:
if not instruction["signed"]:
output_file.write(
" register_%s <= %s %s $unsigned(register_%s);\n"%(
instruction["dest"],
instruction["left"],
instruction["op"],
instruction["src"]))
else:
#Verilog uses >>> as an arithmetic right shift
if instruction["op"] == ">>":
instruction["op"] = ">>>"
output_file.write(
" register_%s <= %s %s $signed(register_%s);\n"%(
instruction["dest"],
instruction["left"],
instruction["op"],
instruction["src"]))
elif instruction["op"] in ["float_to_int"]:
output_file.write(" float_to <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= to_int;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" float_to_int_go <= 1;\n")
output_file.write(" if (float_to_int_done) begin\n")
output_file.write(" float_to_int_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
 
elif instruction["op"] in binary_operators and "right" in instruction:
if not instruction["signed"]:
output_file.write(
" register_%s <= $unsigned(register_%s) %s %s;\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["right"]))
else:
#Verilog uses >>> as an arithmetic right shift
if instruction["op"] == ">>":
instruction["op"] = ">>>"
output_file.write(
" register_%s <= $signed(register_%s) %s %s;\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["right"]))
elif instruction["op"] in binary_operators and "left" in instruction:
if ("type" in instruction and
instruction["type"] == "float" and
instruction["op"] in ["+", "-", "*", "/"]):
 
elif instruction["op"] in binary_operators:
if not instruction["signed"]:
output_file.write(
" register_%s <= $unsigned(register_%s) %s $unsigned(register_%s);\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["srcb"]))
else:
#Verilog uses >>> as an arithmetic right shift
if instruction["op"] == ">>":
instruction["op"] = ">>>"
output_file.write(
" register_%s <= $signed(register_%s) %s $signed(register_%s);\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["srcb"]))
if instruction["op"] == "+":
output_file.write(" adder_a <= %s;\n"%(instruction["left"]))
output_file.write(" adder_b <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= adder_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" adder_go <= 1;\n")
output_file.write(" if (adder_done) begin\n")
output_file.write(" adder_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
if instruction["op"] == "-":
output_file.write(" adder_a <= %s;\n"%(instruction["left"]))
output_file.write(" adder_b <= {~register_%s[31], register_%s[30:0]};\n"%(
instruction["src"],
instruction["src"]))
output_file.write(" register_%s <= adder_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" adder_go <= 1;\n")
output_file.write( " if (adder_done) begin\n")
output_file.write(" adder_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "*":
output_file.write(" multiplier_a <= %s;\n"%(instruction["left"]))
output_file.write(" multiplier_b <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= multiplier_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" multiplier_go <= 1;\n")
output_file.write( " if (multiplier_done) begin\n")
output_file.write(" multiplier_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "/":
output_file.write(" divider_a <= %s;\n"%(instruction["left"]))
output_file.write(" divider_b <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= divider_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" divider_go <= 1;\n")
output_file.write(" if (divider_done) begin\n")
output_file.write(" divider_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif not instruction["signed"]:
output_file.write(
" register_%s <= %s %s $unsigned(register_%s);\n"%(
instruction["dest"],
instruction["left"],
instruction["op"],
instruction["src"]))
else:
#Verilog uses >>> as an arithmetic right shift
if instruction["op"] == ">>":
instruction["op"] = ">>>"
output_file.write(
" register_%s <= %s %s $signed(register_%s);\n"%(
instruction["dest"],
sign_extend(instruction["left"], instruction["size"]),
instruction["op"],
instruction["src"]))
 
elif instruction["op"] == "jmp_if_false":
output_file.write(" if (register_%s == 0)\n"%(instruction["src"]));
output_file.write(" program_counter <= %s;\n"%to_gray(instruction["label"]&0xffff))
elif instruction["op"] in binary_operators and "right" in instruction:
if ("type" in instruction and
instruction["type"] == "float" and
instruction["op"] in ["+", "-", "*", "/"]):
 
elif instruction["op"] == "jmp_if_true":
output_file.write(" if (register_%s != 0)\n"%(instruction["src"]));
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff))
if instruction["op"] == "+":
output_file.write(" adder_b <= %s;\n"%(instruction["right"]))
output_file.write(" adder_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= adder_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" adder_go <= 1;\n")
output_file.write(" if (adder_done) begin\n")
output_file.write(" adder_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
if instruction["op"] == "-":
output_file.write(" adder_b <= %s;\n"%(
instruction["right"] ^ 0x80000000))
output_file.write(" adder_a <= register_%s;\n"%(
instruction["src"]))
output_file.write(" register_%s <= adder_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" adder_go <= 1;\n")
output_file.write(" if (adder_done) begin\n")
output_file.write(" adder_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "*":
output_file.write(" multiplier_b <= %s;\n"%(instruction["right"]))
output_file.write(" multiplier_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= multiplier_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" multiplier_go <= 1;\n")
output_file.write(" if (multiplier_done) begin\n")
output_file.write(" multiplier_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "/":
output_file.write(" divider_b <= %s;\n"%(instruction["right"]))
output_file.write(" divider_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" register_%s <= divider_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" divider_go <= 1;\n")
output_file.write(" if (divider_done) begin\n")
output_file.write(" divider_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
 
elif instruction["op"] == "jmp_and_link":
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff))
output_file.write(" register_%s <= 16'd%s;\n"%(
instruction["dest"], to_gray((location+1)&0xffff)))
elif not instruction["signed"]:
output_file.write(
" register_%s <= $unsigned(register_%s) %s %s;\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["right"]))
else:
#Verilog uses >>> as an arithmetic right shift
if instruction["op"] == ">>":
instruction["op"] = ">>>"
output_file.write(
" register_%s <= $signed(register_%s) %s %s;\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
sign_extend(instruction["right"], instruction["size"])))
 
elif instruction["op"] == "jmp_to_reg":
output_file.write(
" program_counter <= register_%s;\n"%instruction["src"])
elif instruction["op"] in binary_operators:
if ("type" in instruction and
instruction["type"] == "float" and
instruction["op"] in ["+", "-", "*", "/"]):
 
elif instruction["op"] == "goto":
output_file.write(" program_counter <= 16'd%s;\n"%(to_gray(instruction["label"]&0xffff)))
if instruction["op"] == "+":
output_file.write(" adder_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" adder_b <= register_%s;\n"%(instruction["srcb"]))
output_file.write(" register_%s <= adder_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" adder_go <= 1;\n")
output_file.write(" if (adder_done) begin\n")
output_file.write(" adder_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
if instruction["op"] == "-":
output_file.write(" adder_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" adder_b <= {~register_%s[31], register_%s[30:0]};\n"%(
instruction["srcb"],
instruction["srcb"]))
output_file.write(" register_%s <= adder_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" adder_go <= 1;\n")
output_file.write(" if (adder_done) begin\n")
output_file.write(" adder_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "*":
output_file.write(" multiplier_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" multiplier_b <= register_%s;\n"%(instruction["srcb"]))
output_file.write(" register_%s <= multiplier_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" multiplier_go <= 1;\n")
output_file.write(" if (multiplier_done) begin\n")
output_file.write(" multiplier_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "/":
output_file.write(" divider_a <= register_%s;\n"%(instruction["src"]))
output_file.write(" divider_b <= register_%s;\n"%(instruction["srcb"]))
output_file.write(" register_%s <= divider_z;\n"%(instruction["dest"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" divider_go <= 1;\n")
output_file.write(" if (divider_done) begin\n")
output_file.write(" divider_go <= 0;\n")
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
 
elif instruction["op"] == "file_read":
output_file.write(" file_count = $fscanf(%s, \"%%d\\n\", register_%s);\n"%(
input_files[instruction["file_name"]], instruction["dest"]))
elif not instruction["signed"]:
output_file.write(
" register_%s <= $unsigned(register_%s) %s $unsigned(register_%s);\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["srcb"]))
else:
#Verilog uses >>> as an arithmetic right shift
if instruction["op"] == ">>":
instruction["op"] = ">>>"
output_file.write(
" register_%s <= $signed(register_%s) %s $signed(register_%s);\n"%(
instruction["dest"],
instruction["src"],
instruction["op"],
instruction["srcb"]))
 
elif instruction["op"] == "file_write":
output_file.write(" $fdisplay(%s, \"%%d\", register_%s);\n"%(
output_files[instruction["file_name"]], instruction["src"]))
elif instruction["op"] == "jmp_if_false":
output_file.write(" if (register_%s == 0)\n"%(instruction["src"]));
output_file.write(" program_counter <= %s;\n"%to_gray(instruction["label"]&0xffff))
 
elif instruction["op"] == "read":
output_file.write(" register_%s <= input_%s;\n"%(
instruction["dest"], instruction["input"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" s_input_%s_ack <= 1'b1;\n"%instruction["input"])
output_file.write( " if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%(
instruction["input"],
instruction["input"]
))
output_file.write(" s_input_%s_ack <= 1'b0;\n"%instruction["input"])
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "jmp_if_true":
output_file.write(" if (register_%s != 0)\n"%(instruction["src"]));
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff))
 
elif instruction["op"] == "ready":
output_file.write(" register_%s <= 0;\n"%instruction["dest"])
output_file.write(" register_%s[0] <= input_%s_stb;\n"%(
instruction["dest"], instruction["input"]))
elif instruction["op"] == "jmp_and_link":
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(instruction["label"]&0xffff))
output_file.write(" register_%s <= 16'd%s;\n"%(
instruction["dest"], to_gray((location+1)&0xffff)))
 
elif instruction["op"] == "write":
output_file.write(" s_output_%s <= register_%s;\n"%(
instruction["output"], instruction["src"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" s_output_%s_stb <= 1'b1;\n"%instruction["output"])
output_file.write(
" if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%(
instruction["output"],
instruction["output"]
))
output_file.write(" s_output_%s_stb <= 1'b0;\n"%instruction["output"])
output_file.write(" program_counter <= %s;\n"%to_gray(location+1))
output_file.write(" end\n")
elif instruction["op"] == "jmp_to_reg":
output_file.write(
" program_counter <= register_%s;\n"%instruction["src"])
 
elif instruction["op"] == "memory_read_request":
output_file.write(
" address_%s <= register_%s;\n"%(
instruction["element_size"],
instruction["src"])
)
elif instruction["op"] == "goto":
output_file.write(" program_counter <= 16'd%s;\n"%(to_gray(instruction["label"]&0xffff)))
 
elif instruction["op"] == "memory_read_wait":
pass
elif instruction["op"] == "file_read":
output_file.write(" file_count = $fscanf(%s, \"%%d\\n\", register_%s);\n"%(
input_files[instruction["file_name"]], instruction["dest"]))
 
elif instruction["op"] == "memory_read":
output_file.write(
" register_%s <= data_out_%s;\n"%(
instruction["dest"],
instruction["element_size"])
)
elif instruction["op"] == "file_write":
if instruction["type"] == "float":
output_file.write(' fp_value = (register_%s[31]?-1.0:1.0) *\n'%instruction["src"])
output_file.write(' (2.0 ** (register_%s[30:23]-127.0)) *\n'%instruction["src"])
output_file.write(' ({1\'d1, register_%s[22:0]} / (2.0**23));\n'%instruction["src"])
 
elif instruction["op"] == "memory_write":
output_file.write(" address_%s <= register_%s;\n"%(
instruction["element_size"],
instruction["src"])
)
output_file.write(" data_in_%s <= register_%s;\n"%(
instruction["element_size"],
instruction["srcb"])
)
output_file.write(" write_enable_%s <= 1'b1;\n"%(
instruction["element_size"])
)
output_file.write(' $fdisplay(%s, fp_value);\n'%(
output_files[instruction["file_name"]]))
else:
output_file.write(" $fdisplay(%s, \"%%d\", register_%s);\n"%(
output_files[instruction["file_name"]], instruction["src"]))
 
elif instruction["op"] == "memory_write_literal":
output_file.write(" address_%s <= 16'd%s;\n"%(
instruction["element_size"],
instruction["address"])
)
output_file.write(" data_in_%s <= %s;\n"%(
instruction["element_size"],
instruction["value"])
)
output_file.write(" write_enable_%s <= 1'b1;\n"%(
instruction["element_size"])
)
elif instruction["op"] == "read":
output_file.write(" register_%s <= input_%s;\n"%(
instruction["dest"], instruction["input"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" s_input_%s_ack <= 1'b1;\n"%instruction["input"])
output_file.write( " if (s_input_%s_ack == 1'b1 && input_%s_stb == 1'b1) begin\n"%(
instruction["input"],
instruction["input"]
))
output_file.write(" s_input_%s_ack <= 1'b0;\n"%instruction["input"])
output_file.write(" program_counter <= 16'd%s;\n"%to_gray(location+1))
output_file.write(" end\n")
 
elif instruction["op"] == "assert":
output_file.write( " if (register_%s == 0) begin\n"%instruction["src"])
output_file.write( " $display(\"Assertion failed at line: %s in file: %s\");\n"%(
instruction["line"],
instruction["file"]
))
output_file.write( " $finish_and_return(1);\n")
output_file.write( " end\n")
elif instruction["op"] == "ready":
output_file.write(" register_%s <= 0;\n"%instruction["dest"])
output_file.write(" register_%s[0] <= input_%s_stb;\n"%(
instruction["dest"], instruction["input"]))
 
elif instruction["op"] == "wait_clocks":
output_file.write(" if (timer < register_%s) begin\n"%instruction["src"])
output_file.write(" program_counter <= program_counter;\n")
output_file.write(" timer <= timer+1;\n")
output_file.write(" end\n")
elif instruction["op"] == "write":
output_file.write(" s_output_%s <= register_%s;\n"%(
instruction["output"], instruction["src"]))
output_file.write(" program_counter <= %s;\n"%to_gray(location))
output_file.write(" s_output_%s_stb <= 1'b1;\n"%instruction["output"])
output_file.write(
" if (s_output_%s_stb == 1'b1 && output_%s_ack == 1'b1) begin\n"%(
instruction["output"],
instruction["output"]
))
output_file.write(" s_output_%s_stb <= 1'b0;\n"%instruction["output"])
output_file.write(" program_counter <= %s;\n"%to_gray(location+1))
output_file.write(" end\n")
 
elif instruction["op"] == "report":
if not instruction["signed"]:
output_file.write(
' $display ("%%d (report at line: %s in file: %s)", $unsigned(register_%s));\n'%(
instruction["line"],
instruction["file"],
instruction["src"],
))
else:
output_file.write(
' $display ("%%d (report at line: %s in file: %s)", $signed(register_%s));\n'%(
instruction["line"],
instruction["file"],
instruction["src"],
))
elif instruction["op"] == "memory_read_request":
output_file.write(
" address_%s <= register_%s;\n"%(
instruction["element_size"],
instruction["src"]))
 
elif instruction["op"] == "stop":
#If we are in testbench mode stop the simulation
#If we are part of a larger design, other C programs may still be running
for file_ in input_files.values():
output_file.write(" $fclose(%s);\n"%file_)
for file_ in output_files.values():
output_file.write(" $fclose(%s);\n"%file_)
if testbench:
output_file.write(' $finish;\n')
output_file.write(" program_counter <= program_counter;\n")
elif instruction["op"] == "memory_read_wait":
pass
 
elif instruction["op"] == "memory_read":
output_file.write(
" register_%s <= data_out_%s;\n"%(
instruction["dest"],
instruction["element_size"]))
 
elif instruction["op"] == "memory_write":
output_file.write(" address_%s <= register_%s;\n"%(
instruction["element_size"],
instruction["src"]))
output_file.write(" data_in_%s <= register_%s;\n"%(
instruction["element_size"],
instruction["srcb"]))
output_file.write(" write_enable_%s <= 1'b1;\n"%(
instruction["element_size"]))
 
elif instruction["op"] == "memory_write_literal":
output_file.write(" address_%s <= 16'd%s;\n"%(
instruction["element_size"],
instruction["address"]))
output_file.write(" data_in_%s <= %s;\n"%(
instruction["element_size"],
instruction["value"]))
output_file.write(" write_enable_%s <= 1'b1;\n"%(
instruction["element_size"]))
 
elif instruction["op"] == "assert":
output_file.write( " if (register_%s == 0) begin\n"%instruction["src"])
output_file.write( " $display(\"Assertion failed at line: %s in file: %s\");\n"%(
instruction["line"],
instruction["file"]))
output_file.write( " $finish_and_return(1);\n")
output_file.write( " end\n")
 
elif instruction["op"] == "wait_clocks":
output_file.write(" if (timer < register_%s) begin\n"%instruction["src"])
output_file.write(" program_counter <= program_counter;\n")
output_file.write(" timer <= timer+1;\n")
output_file.write(" end\n")
 
elif instruction["op"] == "report":
if instruction["type"] == "float":
output_file.write(' fp_value = (register_%s[31]?-1.0:1.0) *\n'%instruction["src"])
output_file.write(' (2.0 ** (register_%s[30:23]-127.0)) *\n'%instruction["src"])
output_file.write(' ({1\'d1, register_%s[22:0]} / (2.0**23));\n'%instruction["src"])
 
output_file.write(' $display ("%%f (report at line: %s in file: %s)", fp_value);\n'%(
instruction["line"],
instruction["file"]))
elif not instruction["signed"]:
output_file.write(
' $display ("%%d (report at line: %s in file: %s)", $unsigned(register_%s));\n'%(
instruction["line"],
instruction["file"],
instruction["src"]))
else:
output_file.write(
' $display ("%%d (report at line: %s in file: %s)", $signed(register_%s));\n'%(
instruction["line"],
instruction["file"],
instruction["src"]))
 
elif instruction["op"] == "stop":
#If we are in testbench mode stop the simulation
#If we are part of a larger design, other C programs may still be running
for file_ in input_files.values():
output_file.write(" $fclose(%s);\n"%file_)
for file_ in output_files.values():
output_file.write(" $fclose(%s);\n"%file_)
if testbench:
output_file.write(' $finish;\n')
output_file.write(" program_counter <= program_counter;\n")
output_file.write(" end\n\n")
 
output_file.write(" endcase\n")
 
#Reset program counter and control signals
output_file.write(" if (rst == 1'b1) begin\n")
output_file.write(" program_counter <= 0;\n")
for i in inputs:
output_file.write(" s_input_%s_ack <= 0;\n"%(i))
for i in outputs:
output_file.write(" s_output_%s_stb <= 0;\n"%(i))
output_file.write(" end\n")
output_file.write(" end\n")
for i in inputs:
output_file.write(" assign input_%s_ack = s_input_%s_ack;\n"%(i, i))
for i in outputs:
output_file.write(" assign output_%s_stb = s_output_%s_stb;\n"%(i, i))
output_file.write(" assign output_%s = s_output_%s;\n"%(i, i))
output_file.write("\nendmodule\n")
 
return inputs, outputs
 
def connect_float_to_int(output_file):
output_file.write(" \n float_to_int float_to_int_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(float_to),\n")
output_file.write(" .input_a_stb(float_to_stb),\n")
output_file.write(" .input_a_ack(float_to_ack),\n")
output_file.write(" .output_z(to_int),\n")
output_file.write(" .output_z_stb(to_int_stb),\n")
output_file.write(" .output_z_ack(to_int_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" float_to_int_done <= 0;\n")
output_file.write(" case(float_to_int_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (float_to_int_go) begin\n")
output_file.write(" float_to_int_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" float_to_stb <= 1;\n")
output_file.write(" if (float_to_stb && float_to_ack) begin\n")
output_file.write(" float_to_stb <= 0;\n")
output_file.write(" float_to_int_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" to_int_ack <= 1;\n")
output_file.write(" if (to_int_stb && to_int_ack) begin\n")
output_file.write(" to_int_ack <= 0;\n")
output_file.write(" float_to_int_state <= wait_next;\n")
output_file.write(" float_to_int_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" wait_next:\n")
output_file.write(" begin\n")
output_file.write(" if (!float_to_int_go) begin\n")
output_file.write(" float_to_int_state <= wait_go;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" float_to_int_state <= wait_go;\n")
output_file.write(" float_to_stb <= 0;\n")
output_file.write(" to_int_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
output_file.write(" endcase\n")
def connect_int_to_float(output_file):
output_file.write(" \n int_to_float int_to_float_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(int_to),\n")
output_file.write(" .input_a_stb(int_to_stb),\n")
output_file.write(" .input_a_ack(int_to_ack),\n")
output_file.write(" .output_z(to_float),\n")
output_file.write(" .output_z_stb(to_float_stb),\n")
output_file.write(" .output_z_ack(to_float_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" int_to_float_done <= 0;\n")
output_file.write(" case(int_to_float_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (int_to_float_go) begin\n")
output_file.write(" int_to_float_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" int_to_stb <= 1;\n")
output_file.write(" if (int_to_stb && int_to_ack) begin\n")
output_file.write(" int_to_stb <= 0;\n")
output_file.write(" int_to_float_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" to_float_ack <= 1;\n")
output_file.write(" if (to_float_stb && to_float_ack) begin\n")
output_file.write(" to_float_ack <= 0;\n")
output_file.write(" int_to_float_state <= wait_next;\n")
output_file.write(" int_to_float_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" wait_next:\n")
output_file.write(" begin\n")
output_file.write(" if (!int_to_float_go) begin\n")
output_file.write(" int_to_float_state <= wait_go;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" int_to_float_state <= wait_go;\n")
output_file.write(" int_to_stb <= 0;\n")
output_file.write(" to_float_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
#Reset program counter and control signals
output_file.write(" if (rst == 1'b1) begin\n")
output_file.write(" program_counter <= 0;\n")
for i in inputs:
output_file.write(" s_input_%s_ack <= 0;\n"%(i))
for i in outputs:
output_file.write(" s_output_%s_stb <= 0;\n"%(i))
output_file.write(" end\n")
output_file.write(" end\n")
for i in inputs:
output_file.write(" assign input_%s_ack = s_input_%s_ack;\n"%(i, i))
for i in outputs:
output_file.write(" assign output_%s_stb = s_output_%s_stb;\n"%(i, i))
output_file.write(" assign output_%s = s_output_%s;\n"%(i, i))
output_file.write("\nendmodule\n")
def connect_divider(output_file):
output_file.write(" \n divider divider_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(divider_a),\n")
output_file.write(" .input_a_stb(divider_a_stb),\n")
output_file.write(" .input_a_ack(divider_a_ack),\n")
output_file.write(" .input_b(divider_b),\n")
output_file.write(" .input_b_stb(divider_b_stb),\n")
output_file.write(" .input_b_ack(divider_b_ack),\n")
output_file.write(" .output_z(divider_z),\n")
output_file.write(" .output_z_stb(divider_z_stb),\n")
output_file.write(" .output_z_ack(divider_z_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" divider_done <= 0;\n")
output_file.write(" case(div_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (divider_go) begin\n")
output_file.write(" div_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" divider_a_stb <= 1;\n")
output_file.write(" if (divider_a_stb && divider_a_ack) begin\n")
output_file.write(" divider_a_stb <= 0;\n")
output_file.write(" div_state <= write_b;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_b:\n")
output_file.write(" begin\n")
output_file.write(" divider_b_stb <= 1;\n")
output_file.write(" if (divider_b_stb && divider_b_ack) begin\n")
output_file.write(" divider_b_stb <= 0;\n")
output_file.write(" div_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" divider_z_ack <= 1;\n")
output_file.write(" if (divider_z_stb && divider_z_ack) begin\n")
output_file.write(" divider_z_ack <= 0;\n")
output_file.write(" div_state <= wait_next;\n")
output_file.write(" divider_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" wait_next:\n")
output_file.write(" begin\n")
output_file.write(" if (!divider_go) begin\n")
output_file.write(" div_state <= wait_go;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" div_state <= wait_go;\n")
output_file.write(" divider_a_stb <= 0;\n")
output_file.write(" divider_b_stb <= 0;\n")
output_file.write(" divider_z_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
return inputs, outputs
def connect_multiplier(output_file):
output_file.write(" \n multiplier multiplier_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(multiplier_a),\n")
output_file.write(" .input_a_stb(multiplier_a_stb),\n")
output_file.write(" .input_a_ack(multiplier_a_ack),\n")
output_file.write(" .input_b(multiplier_b),\n")
output_file.write(" .input_b_stb(multiplier_b_stb),\n")
output_file.write(" .input_b_ack(multiplier_b_ack),\n")
output_file.write(" .output_z(multiplier_z),\n")
output_file.write(" .output_z_stb(multiplier_z_stb),\n")
output_file.write(" .output_z_ack(multiplier_z_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" multiplier_done <= 0;\n")
output_file.write(" case(mul_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (multiplier_go) begin\n")
output_file.write(" mul_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" multiplier_a_stb <= 1;\n")
output_file.write(" if (multiplier_a_stb && multiplier_a_ack) begin\n")
output_file.write(" multiplier_a_stb <= 0;\n")
output_file.write(" mul_state <= write_b;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_b:\n")
output_file.write(" begin\n")
output_file.write(" multiplier_b_stb <= 1;\n")
output_file.write(" if (multiplier_b_stb && multiplier_b_ack) begin\n")
output_file.write(" multiplier_b_stb <= 0;\n")
output_file.write(" mul_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" multiplier_z_ack <= 1;\n")
output_file.write(" if (multiplier_z_stb && multiplier_z_ack) begin\n")
output_file.write(" multiplier_z_ack <= 0;\n")
output_file.write(" mul_state <= wait_next;\n")
output_file.write(" multiplier_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" wait_next:\n")
output_file.write(" begin\n")
output_file.write(" if (!multiplier_go) begin\n")
output_file.write(" mul_state <= wait_go;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n\n")
output_file.write(" if (rst) begin\n")
output_file.write(" mul_state <= wait_go;\n")
output_file.write(" multiplier_a_stb <= 0;\n")
output_file.write(" multiplier_b_stb <= 0;\n")
output_file.write(" multiplier_z_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def connect_adder(output_file):
output_file.write(" \n adder adder_1(\n")
output_file.write(" .clk(clk),\n")
output_file.write(" .rst(rst),\n")
output_file.write(" .input_a(adder_a),\n")
output_file.write(" .input_a_stb(adder_a_stb),\n")
output_file.write(" .input_a_ack(adder_a_ack),\n")
output_file.write(" .input_b(adder_b),\n")
output_file.write(" .input_b_stb(adder_b_stb),\n")
output_file.write(" .input_b_ack(adder_b_ack),\n")
output_file.write(" .output_z(adder_z),\n")
output_file.write(" .output_z_stb(adder_z_stb),\n")
output_file.write(" .output_z_ack(adder_z_ack)\n")
output_file.write(" );\n\n")
output_file.write(" \n always @(posedge clk)\n")
output_file.write(" begin\n\n")
output_file.write(" adder_done <= 0;\n")
output_file.write(" case(add_state)\n\n")
output_file.write(" wait_go:\n")
output_file.write(" begin\n")
output_file.write(" if (adder_go) begin\n")
output_file.write(" add_state <= write_a;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_a:\n")
output_file.write(" begin\n")
output_file.write(" adder_a_stb <= 1;\n")
output_file.write(" if (adder_a_stb && adder_a_ack) begin\n")
output_file.write(" adder_a_stb <= 0;\n")
output_file.write(" add_state <= write_b;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" write_b:\n")
output_file.write(" begin\n")
output_file.write(" adder_b_stb <= 1;\n")
output_file.write(" if (adder_b_stb && adder_b_ack) begin\n")
output_file.write(" adder_b_stb <= 0;\n")
output_file.write(" add_state <= read_z;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
output_file.write(" read_z:\n")
output_file.write(" begin\n")
output_file.write(" adder_z_ack <= 1;\n")
output_file.write(" if (adder_z_stb && adder_z_ack) begin\n")
output_file.write(" adder_z_ack <= 0;\n")
output_file.write(" add_state <= wait_next;\n")
output_file.write(" adder_done <= 1;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" wait_next:\n")
output_file.write(" begin\n")
output_file.write(" if (!adder_go) begin\n")
output_file.write(" add_state <= wait_go;\n")
output_file.write(" end\n")
output_file.write(" end\n")
output_file.write(" endcase\n")
output_file.write(" if (rst) begin\n")
output_file.write(" add_state <= wait_go;\n")
output_file.write(" adder_a_stb <= 0;\n")
output_file.write(" adder_b_stb <= 0;\n")
output_file.write(" adder_z_ack <= 0;\n")
output_file.write(" end\n")
output_file.write(" end\n\n")
 
def generate_float_to_int_signals(output_file):
output_file.write(" reg [31:0] float_to;\n")
output_file.write(" reg float_to_stb;\n")
output_file.write(" wire float_to_ack;\n")
output_file.write(" wire [31:0] to_int;\n")
output_file.write(" wire to_int_stb;\n")
output_file.write(" reg to_int_ack;\n")
output_file.write(" reg [2:0] float_to_int_state;\n")
output_file.write(" reg float_to_int_go;\n")
output_file.write(" reg float_to_int_done;\n")
 
def generate_int_to_float_signals(output_file):
output_file.write(" reg [31:0] int_to;\n")
output_file.write(" reg int_to_stb;\n")
output_file.write(" wire int_to_ack;\n")
output_file.write(" wire [31:0] to_float;\n")
output_file.write(" wire to_float_stb;\n")
output_file.write(" reg to_float_ack;\n")
output_file.write(" reg [2:0] int_to_float_state;\n")
output_file.write(" reg int_to_float_go;\n")
output_file.write(" reg int_to_float_done;\n")
 
def generate_divider_signals(output_file):
output_file.write(" reg [31:0] divider_a;\n")
output_file.write(" reg divider_a_stb;\n")
output_file.write(" wire divider_a_ack;\n")
output_file.write(" reg [31:0] divider_b;\n")
output_file.write(" reg divider_b_stb;\n")
output_file.write(" wire divider_b_ack;\n")
output_file.write(" wire [31:0] divider_z;\n")
output_file.write(" wire divider_z_stb;\n")
output_file.write(" reg divider_z_ack;\n")
output_file.write(" reg [2:0] div_state;\n")
output_file.write(" reg divider_go;\n")
output_file.write(" reg divider_done;\n")
 
def generate_multiplier_signals(output_file):
output_file.write(" reg [31:0] multiplier_a;\n")
output_file.write(" reg multiplier_a_stb;\n")
output_file.write(" wire multiplier_a_ack;\n")
output_file.write(" reg [31:0] multiplier_b;\n")
output_file.write(" reg multiplier_b_stb;\n")
output_file.write(" wire multiplier_b_ack;\n")
output_file.write(" wire [31:0] multiplier_z;\n")
output_file.write(" wire multiplier_z_stb;\n")
output_file.write(" reg multiplier_z_ack;\n")
output_file.write(" reg [2:0] mul_state;\n")
output_file.write(" reg multiplier_go;\n")
output_file.write(" reg multiplier_done;\n")
 
def generate_adder_signals(output_file):
output_file.write(" reg [31:0] adder_a;\n")
output_file.write(" reg adder_a_stb;\n")
output_file.write(" wire adder_a_ack;\n")
output_file.write(" reg [31:0] adder_b;\n")
output_file.write(" reg adder_b_stb;\n")
output_file.write(" wire adder_b_ack;\n")
output_file.write(" wire [31:0] adder_z;\n")
output_file.write(" wire adder_z_stb;\n")
output_file.write(" reg adder_z_ack;\n")
output_file.write(" reg [2:0] add_state;\n")
output_file.write(" reg adder_go;\n")
output_file.write(" reg adder_done;\n")
chips/compiler Property changes : Added: svn:ignore ## -0,0 +1 ## +*.bak Index: setup.py =================================================================== --- setup.py (revision 3) +++ setup.py (revision 4) @@ -6,7 +6,7 @@ version="0.1.2", description="Design hardware with Python", long_description="""\ - + Chips ----- @@ -21,7 +21,7 @@ - Automatic generation of synthesisable Verilog. """, - + author="Jon Dawson", author_email="chips@jondawson.org.uk", url="http://github.com/dawsonjon/Chips-2.0", @@ -38,12 +38,11 @@ "Topic :: Software Development :: Code Generators", ], packages=[ - "chips", - "chips.compiler", - "chips.api" + "chips", + "chips.compiler", + "chips.api" ], scripts=[ "c2verilog" ] ) -
/scripts/copy_docs
0,0 → 1,7
#!/bin/bash
 
cp -r docs/build/html ../chips_web/Chips-2.0
cd ../chips_web/Chip2-2.0
git add .
git commit -a -m "Update Documents"
git push
scripts/copy_docs Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: scripts/update_fpu.py =================================================================== --- scripts/update_fpu.py (nonexistent) +++ scripts/update_fpu.py (revision 4) @@ -0,0 +1,15 @@ +#!/usr/bin/env python +import os.path + +divider = open(os.path.join("fpu", "divider", "divider.v")).read() +multiplier = open(os.path.join("fpu", "multiplier", "multiplier.v")).read() +adder = open(os.path.join("fpu", "adder", "adder.v")).read() +int_to_float = open(os.path.join("fpu", "int_to_float", "int_to_float.v")).read() +float_to_int = open(os.path.join("fpu", "float_to_int", "float_to_int.v")).read() +output_file = open(os.path.join("chips", "compiler", "fpu.py"), "w") + +output_file.write("divider = \"\"\"%s\"\"\"\n"%divider) +output_file.write("multiplier = \"\"\"%s\"\"\"\n"%multiplier) +output_file.write("adder = \"\"\"%s\"\"\"\n"%adder) +output_file.write("int_to_float = \"\"\"%s\"\"\"\n"%int_to_float) +output_file.write("float_to_int = \"\"\"%s\"\"\"\n"%float_to_int)
scripts/update_fpu.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: test_suite/.gitignore =================================================================== --- test_suite/.gitignore (revision 3) +++ test_suite/.gitignore (revision 4) @@ -2,3 +2,4 @@ real_main test arbiter +test_file Index: test_suite/.coverage =================================================================== --- test_suite/.coverage (revision 3) +++ test_suite/.coverage (revision 4) @@ -1,29 +1,29 @@ €}q(U collectorqU -coverage v3.4qUlinesq}q(U)/usr/share/pyshared/coverage/collector.pyq]q(KèKéKëKöK÷eUB/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/optimizer.pyq]q (KKKKK KKKKKKKKKKKKKKK K"K#K$K&K(K)K*K+K,K-K.K0K1K2K3K4K5K6K8K:K=K>K?K@KAKBKEKFKGKHKKKLKMKNKOKQKSKUKWK[K\K]K_KcKdKeKfKgKiKmKnKpKqKsKtKvKwKyK}K~KK€K‚K†KˆKŒKKK•K–K—K˜K™KšK›KœKKžKŸK K¡K¢K£K¤K¥K§K©KªK«K­K±K²K³K´KµK¶K·K¸K¹KºK»K¼K½K¾K¿KÁKÂKÃKÄKÅKÇeUA/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/compiler.pyq -]q (KKKKKK K K K -KKKKKKKKKKKKKK K!K"K#K$K%K&K'K(K)K*K+K,K-K.K/K0K5K6K7K8K9K:K;K>K?K@KAKBKCKDKEKFKGKHKIKJKKKLKNKOKPKQKTeU?/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/tokens.pyq ]q -(KKKKKKK K K -KKKKKKKKKKKK!K#K$K%K)K*K+K,K/K0K1K2K3K4K5K6K7K8K9K:K;KK?KAKBKEKFKGKIKLKMKNKPKSKTKUKWKXK[K\K]K_K`KcKdKeKfKgKjKlKmKpKqKrKsKtKvKyKzK{K}K~KKƒK„K†KˆKŒKŽK’K“K—K›KœKKžKŸK¡K¥K§K¬K­K®K¯K°K±K³eUF/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/verilog_speed.pyq]q(KKKKKK KKKKKKKKKK)K.K/K0K1K2K3K5K6K7K:K;KK?KAKBKEKFKGKIKLKMKNKPKSKTKUKWKXK[K\K]K_K`KcKdKeKfKgKjKlKmKpKqKrKsKtKvKyKzK{K}K~KKƒK„K†KˆKŒKŽK’K“K—K›KœKKžKŸK¡K¥K§K¬K­K®K¯K°K±K³eUA/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/__init__.pyq +]q KaUB/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/allocator.pyq ]q +(KKKKKK K +K K K +KKKKKKKKKKKKKKKK K$K%K&K'K(K)K*K+K-K.K/eUF/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/verilog_speed.pyq]q(KKKKKK KKKKKKKKKK)K.K/K0K1K2K3K5K6K7K:K;KM?M@MCMEMFMGMHMIMJMLMMMNMOMPMQMRMSMVMWMXMYMZM[M\M]M_M`MaMbMcMdMeMfMiMjMkMlMmMnMoMpMrMsMtMvMwMxMzM{M|M}MM€MMƒM„M†MŠMŽMMM‘M’M“M”M•M—M˜M™M›MœMMžM M¡M¢M£M¤M¥M¦M§M¨MªM«M¬M®M¯M°M±M²MµM¶M¸M¹MºM»M¼M¿MÀMÁMÂMÄMÅMÆMÈMÉMÌMÍMÎMÏMÑMÒMÓMÕMÖMÙMÚMÛMÜMÝMßMàMâMãMäMåMæMèMéMñMòMóMôMõMøMûMýMÿMMMMMMM M M M M -MMMMMMMMeUA/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/__init__.pyq]qKaUC/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/parse_tree.pyq]q(KKKKKKK K -KKKKKKKK"K$K%K&K'K(K)K*K+K,K-K.K/K0K1K3K4K5K6K7K8K9K:KM?M@MAMCMDMEMFMGMIMJMSMTMUMVMWMXMYMZM[M]M^M_M`MbMcMdMeMfMpMqMsMtMvMwMxMyMzM{M|M}MM€MM‚MƒM„M†M‡MˆMŠMŒMMŽMMM‘M’M“M”M–M—M˜M™MšM›MœMMžMŸM M¡M¢M£M¤M¥M¦M§M¨M©MªM«M¬M­M®M¯M°M±M²M´MµM·M¸MºM»M¼M½M¾M¿MÀMÁMÃMÄMÅMÆMÇMÈMÊMËMÍMÎMÏMÐMÑMÒMÓMÔMÕMÖM×MØMÙMÛMÜMÝMÞMßMàMâMãMäMåMçMèMîMóMôMõMöM÷MøMúMûMýMþMMMM M -M M MMMMMMMMMMMMMMMMM M"M#M$M%M&M'M(M)M*M,M-M.M/M0M1M2M3M4M5M6M7M8M9M:M;M<M=M>M?M@MAMBMCMDMEMGMHMIMJMKMLMMMNMPMQMRMSMTMUMVMXMYMZM[M\M]M^M_MaMcMeMfMgMiMjMkMlMmMoMqMrMsMtMuMvMwMxMzM{M|M}M~MM€M‚MƒM„M…M†M‡MˆM‰MŠM‹MŒMMŽMMM’M”M•M–M—M˜M™M›MœMMŸM eUB/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/allocator.pyq]q(KKKKKK K -K K K -KKKKKKKKKKKKKKKK K$K%K&K'K(K)K*K+K-K.K/eUE/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/verilog_area.pyq]q(K K +MMMMMMMMeUA/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/builtins.pyq]q(KKKKKxeU0/media/sdb1/Projects/Chips-Demo/chips2/c2verilogq]q(KKKKKK K K +KKKK!K"K#K$K%K(K)K*K+K,K.eU(/usr/share/pyshared/coverage/execfile.pyq]q(KKKKKK!K"K#K$K&K(K)K*K+K/K1K4K5K6K9KDKGKHeUE/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/verilog_area.pyq]q(K K KKKKKKKKKKK K"K&K'K)K+K/K0K1K2K3K4K5K6K7K8K9K:K;KK?K@KBKCKDKEKGKHKJKNKOKPKQKRKSKTKUKVKWKXKYKZK\K]K_K`KbKcKeKfKhKiKkKlKnKoKqKrKtKuKwKxKyK{K|K}K~K€KK‚K„K…K†KˆK‰K‹KŒKKŽKKK’K”K™KšK›KœKKžK K¡K¢K¥K¦K§K©K«K°K±K²K³K´K»K¼KÃKÄKëKìKïKðKñKóKôKöMMMMM M M M M MMMMMMMMMMMMMMM M!M"M$M%M'M(M)M*M+M-M/M1M2M5M6M:M;M<M=M>M@MBMCMDMEMFMHMJMKMMMNMPMQMSMTMUMVMWMXMZM[M_MaMbMcMdMeMfMgMhMiMkMlMmMnMoMqMrMsMtMuMvMwMzM{M~M€MM‚MƒM„M…M†M‡M‰MŠM‹MŒMMM’M“M”M•M–M—M˜M™MšMœMMžMŸM M¡M¢M£M¤M¥M¦M§M¨MªM¹MºM»M¼M¾M¿MÁMÂMÃMÄMÅMÆMÇMÉMÊMËMÌMÍMÎMÏMÑMÓMÔMÕMÖM×MØMÙMÚMÛMÜMÝMÞMßMàMáMâMãMäMåMæMèMéMêMëMìMíMîMïMðMñMóMôMõMöMùMûMüMýMþMÿMMMMMMMM M M M M MMMMMMMMMMMMMMMM M!M#M$M%M'M(M)M*M+M,M.M/M0M1M2M3M4M6M7M8M9M:M;M<M=M>M?MAMBMCMDMEMFMGMHMIMJMLMMMNMOMPMQMRMSMTMUMWMXMYMZM[M\M]M^M`MaMbMcMdMeMfMgMiMqMxMyMzM{M|M}M~MMM‚MƒM„M…M†M‡MˆMŠM‹MŒMMŽMMM‘M’M”M•M–M—M˜M™M›MœMžMŸM M¡M¢M£M¤M¦M§M¨M©MªM«M¬M­M®M¯M±M²M³M´MµM¶M·M¸M¹MºM¼M½M¾M¿MÀMÁMÂMÃMÄMÆMÇMÈMÉMÎMÏMÐMÑMÓMÖM×MØMÚMÜMÝMÞMßMàMáMäMåMçMéMêMëMìMíMîMïMðMñMòMóMõMöM÷MøMùMúMûMüMýMÿMMMMMMMMMM M M -MMMMMMMMMMMMMMMMMeU(/usr/share/pyshared/coverage/execfile.pyq]q(KKKKKK!K"K#K$K&K(K)K*K+K/K1K4K5K6K9KDKGKHeU0/media/sdb1/Projects/SP605_DEMO/chips2/c2verilogq]q(KKKKKK K K -KKKK!K"K#K$K%K(K)K*K+K,K.eU'/usr/share/pyshared/coverage/control.pyq]qMeaU8/media/sdb1/Projects/SP605_DEMO/chips2/chips/__init__.pyq]qKaU?/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/parser.pyq ]q!(KKKKKKK K K +MMMMMMMMMMMMMMMMMeUC/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/parse_tree.pyq]q(KKKKKKK K +KKKKKKKK"K$K%K&K'K(K)K*K+K,K-K.K/K0K1K3K4K5K6K7K8K9K:KM?M@MAMCMDMEMFMGMIMJMSMTMUMVMWMXMYMZM[M]M^M_M`MbMcMdMeMfMpMqMsMtMvMwMxMyMzM{M|M}MM€MM‚MƒM„M†M‡MˆMŠMŒMMŽMMM‘M’M“M”M–M—M˜M™MšM›MœMMžMŸM M¡M¢M£M¤M¥M¦M§M¨M©MªM«M¬M­M®M¯M°M±M²M´MµM·M¸MºM»M¼M½M¾M¿MÀMÁMÃMÄMÅMÆMÇMÈMÊMËMÍMÎMÏMÐMÑMÒMÓMÔMÕMÖM×MØMÙMÛMÜMÝMÞMßMàMâMãMäMåMçMèMîMóMôMõMöM÷MøMúMûMýMþMMMM M +M M MMMMMMMMMMMMMMMMM M"M#M$M%M&M'M(M)M*M,M-M.M/M0M1M2M3M4M5M6M7M8M9M:M;M<M=M>M?M@MAMBMCMDMEMGMHMIMJMKMLMMMNMPMQMRMSMTMUMVMXMYMZM[M\M]M^M_MaMcMeMfMgMiMjMkMlMmMoMqMrMsMtMuMvMwMxMzM{M|M}M~MM€M‚MƒM„M…M†M‡MˆM‰MŠM‹MŒMMŽMMM’M”M•M–M—M˜M™M›MœMMŸM eUB/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/optimizer.pyq]q(KKKKK KKKKKKKKKKKKKKK K"K#K$K&K(K)K*K+K,K-K.K0K1K2K3K4K5K6K8K:K=K>K?K@KAKBKEKFKGKHKKKLKMKNKOKQKSKUKWK[K\K]K_KcKdKeKfKgKiKmKnKpKqKsKtKvKwKyK}K~KK€K‚K†KˆKŒKKK•K–K—K˜K™KšK›KœKKžKŸK K¡K¢K£K¤K¥K§K©KªK«K­K±K²K³K´KµK¶K·K¸K¹KºK»K¼K½K¾K¿KÁKÂKÃKÄKÅKÇeU'/usr/share/pyshared/coverage/control.pyq]qMeaU8/media/sdb1/Projects/Chips-Demo/chips2/chips/__init__.pyq]qKaUA/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/compiler.pyq ]q!(KKKKKK K K K +KKKKKKKKKKKKKK K!K"K#K$K%K&K'K(K)K*K+K,K-K.K/K0K5K6K7K8K9K:K;K>K?K@KAKBKCKDKEKFKGKHKIKJKKKLKNKOKPKQKTeUC/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/exceptions.pyq"]q#(KKKKKKK K +K KeU?/media/sdb1/Projects/Chips-Demo/chips2/chips/compiler/parser.pyq$]q%(KKKKKKK K K KKKKKKKKKKKKKKKKKK K"K#K$K&K'K)K*K,K-K.K/K2K3K4K6K8K9K:K;KM@MAMBMCMDMEMFMHMIMJMLMMMOMPMQMRMSMTMUMVMWMXMZM[M\M]M^M_M`MaMcMdMeMgMiMjMkMlMmMnMoMpMqMrMsMtMuMwMxMyMzM{M|M}M~MMM‚MƒM„M…M†M‡MˆM‰MŠMŒMMŽMMM‘M’M“M”M•M—M˜M™MšM›MœMMžM M¡M¢M£M¤M¥M§M¨M©MªM«M¬M­M®M°M±M²M³M´MµM¶M·M¹MºM»M¼M¾M¿MÀMÁMÂMÃMÄMÅMÆMÇMÉMÊMËMÌMÎMÐMÑMÒMÔMÕMÖM×MØMÙMÚMÛMÜMÝMÞMßMàMáMâMãMäMåMæMçMèMéMêMëMïMðMñMóMôMõMöM÷MøMùMúMýMÿMMMMMMMMM M M M MMMMMMMMMMMMMMMM M!M"M#M%M'M(M*M+M,M-M.M0M2M3M5M6M7M8M9M;M<M=M>M?MBMCMDMEMFMGMHMIMJMLMMMNMOMPMQMRMTMUMVMWMXMYMZM[M]M_M`MaMbMcMdMeMfMgMhMiMjMkMlMmMnMoMqMsMtMuMvMwMxMyMzM|M~MM€MM‚M„M…M‡MˆM‰MŠM‹MMM‘M˜M¡M¢M£M¤M¥M§M¨M©MªM«M­M®M¯M°M±M²M´MµM¶M·M¸M¹MºM»M½M¿MÀMÁMÂMÃMÄMÅMÇMÈMÊMËMÍMÎMÏMÐMÑMÒMÓMÔMÕMÖM×MÙMÚMÛMÜMÝMÞMßMãMåMæMçMèMéMêMëMìMïMðMñMòMóMôMõMöM÷MøMùMúMûMüMýMMMMMMMM M -M MMMMMMMMMMMMM M!M"M#M$M%M&M'M(M*M,M-M.M/M0M1M3M4eUA/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/builtins.pyq"]q#(KKKKKxeUC/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/exceptions.pyq$]q%(KKKKKKK K -K Keuu. \ No newline at end of file +M MMMMMMMMMMMMM M!M"M#M$M%M&M'M(M*M,M-M.M/M0M1M3M4euu. \ No newline at end of file Index: test_suite/test_c2verilog =================================================================== --- test_suite/test_c2verilog (revision 3) +++ test_suite/test_c2verilog (revision 4) @@ -57,6 +57,767 @@ else: print test, "...pass" +test("float file 1", +""" +void main(){ + file_write(1.0, "test_file"); + file_write(-1.0, "test_file"); + file_write(2.0, "test_file"); + file_write(-2.0, "test_file"); +} +""" +) + +test("float file 2", +""" +void main(){ + assert(file_read("test_file") == 1.0); + assert(file_read("test_file") == -1.0); + assert(file_read("test_file") == 2.0); + assert(file_read("test_file") == -2.0); +} +""" +) + +test_fails("array size1", +""" +int size(){ + return 10; +} +void main(){ + int blah[size()]; +} +""" +) + +test("array size2", +""" +void main(){ + const int b = 10; + int a[b]; +} +""" +) + +test_fails("const 1", +""" +void main(){ + const int blah = 10; + blah = 12; +} +""" +) + +test("const 2", +""" +void main(){ + const int blah = 10; + assert(blah == 10); +} +""" +) + +test_fails("const 3", +""" +void main(){ + const float blah = 10; + blah = 12; +} +""" +) + +test("const 4", +""" +void main(){ + const float blah = 10; + assert(blah == 10.0); +} +""" +) + +test_fails("scope 1", +""" +void test(){ + int test_var = 1; +} + +void main(){ + int blah = test_var; +} +""" +) + +test("inplace float 1", +""" +void main(){ + float test = 1.0; + test *= 2.0; + assert(test == 2.0); + test *= 2.0; + assert(test == 4.0); + test *= 2.0; + assert(test == 8.0); +} +""" +) + +test("inplace float 2", +""" +void main(){ + float test = 1.0; + test += 2.0; + assert(test == 3.0); + test += 2.0; + assert(test == 5.0); + test += 2.0; + assert(test == 7.0); +} +""" +) + +test("inplace float 3", +""" +void main(){ + float test = 1.0; + test -= 2.0; + assert(test == -1.0); + test -= 2.0; + assert(test == -3.0); + test -= 2.0; + assert(test == -5.0); +} +""" +) + +test("inplace float 4", +""" +void main(){ + float test = 1.0; + test /= 2.0; + assert(test == 0.5); + test /= 2.0; + assert(test == 0.25); + test /= 2.0; + assert(test == 0.125); +} +""" +) + +test("inplace float 5", +""" +void main(){ + float test = 1.0; + test *= 2; + assert(test == 2.0); + test *= 2; + assert(test == 4.0); + test *= 2; + assert(test == 8.0); +} +""" +) + +test("inplace float 6", +""" +void main(){ + float test = 1.0; + test += 2; + assert(test == 3.0); + test += 2; + assert(test == 5.0); + test += 2; + assert(test == 7.0); +} +""" +) + +test("inplace float 7", +""" +void main(){ + float test = 1.0; + test -= 2; + assert(test == -1.0); + test -= 2; + assert(test == -3.0); + test -= 2; + assert(test == -5.0); +} +""" +) + +test("inplace float 8", +""" +void main(){ + float test = 1.0; + test /= 2; + assert(test == 0.5); + test /= 2; + assert(test == 0.25); + test /= 2; + assert(test == 0.125); +} +""" +) + +test("float 1", +""" +void main(){ + float test = 0.0; + assert(test == 0.0); +} +""" +) +test("float 2", +""" +void main(){ + float test = 1.0; + assert(test > 0.0); +} +""" +) +test("float 3", +""" +void main(){ + float test = 0.0; + assert(test < 1.0); +} +""" +) +test("float 4", +""" +void main(){ + float test = 0.0; + float a = -1.0; + float b = -2.0; + float c = 2.0; + float d = 2.0; + assert(test > -1.0); + assert(a > b); + assert(b < a); + assert(c >= d); + assert(c <= d); +} +""" +) +test("float 5", +""" +void main(){ + float test = 0.0; + assert(test == 0.0); +} +""" +) +test("float 6", +""" +void main(){ + float blah[10]; + blah[0] = 0.0; + blah[1] = 1.0; + blah[2] = 2.0; + blah[3] = 3.0; + assert(blah[0] == 0.0); + assert(blah[1] == 1.0); + assert(blah[2] == 2.0); + assert(blah[3] == 3.0); +} +""" +) + +test("float 7", +""" +void main(){ + float a = 2.0; + assert(a == 1.0 + 1.0); +} +""" +) + +test("float 8", +""" +void main(){ + float a = 2.0; + float b = 2.0; + assert(a+b == 4.0); +} +""" +) + +test("float 9", +""" +void main(){ + float a = -2.0; + float b = -2.0; + assert(a+b == -4.0); +} +""" +) + +test("float 10", +""" +void main(){ + float a = 2.0; + float b = 2.0; + assert(a-b == -0.0); +} +""" +) + +test("float 11", +""" +void main(){ + float a = 2.0; + float b = 4.0; + assert(a-b == -2.0); +} +""" +) + +test("float 12", +""" +void main(){ + float a = 1.0; + float b = 1.0; + assert(a*b == 1.0); +} +""" +) + +test("float 13", +""" +void main(){ + float a = 1.0; + float b = -1.0; + assert(a*b == -1.0); +} +""" +) + +test("float 14", +""" +void main(){ + float a = -1.0; + float b = -1.0; + assert(a*b == 1.0); +} +""" +) + +test("float 15", +""" +void main(){ + float a = -7.0; + float b = 6.0; + assert(a*b == -42.0); +} +""" +) + +test("float 16", +""" +void main(){ + float a = 6.0; + float b = 6.0; + assert(a/b == 1.0); +} +""" +) + +test("float 17", +""" +void main(){ + float a = 12.0; + float b = 6.0; + assert(a/b == 2.0); +} +""" +) + +test("float 18", +""" +void main(){ + int a = 2; + float b = 2.0; + assert(a+b == 4.0); +} +""" +) + +test("float 19", +""" +void main(){ + int a; + float b = 2.0; + a = b + 1.0; + assert(a == 3); +} +""" +) + +test("float 20", +""" +void main(){ + int a = 2; + float b; + b = a + 1.0; + assert(b == 3.0); +} +""" +) + +test("float 21", +""" +typedef struct {float a; float b;} mystruct; +void main(){ + mystruct a; + a.a = 2.0; + a.b = 3.0; + assert(a.a == 2.0); + assert(a.b == 3.0); + assert(a.a + a.b == 5.0); +} +""" +) +test("float 22", +""" +typedef struct {float a; float b;} mystruct; + +void test(mystruct a){ + assert(a.a == 2.0); + assert(a.b == 3.0); + assert(a.a + a.b == 5.0); +} + +void main(){ + mystruct a; + a.a = 2.0; + a.b = 3.0; + test(a); +} +""" +) + +test("float 23", +""" +void test(float b){ + assert(b/6.0 == 2.0); +} + +void main(){ + int a = 12.0; + test(a); +} +""" +) + +test("float 24", +""" +float test(){ + return 6.0; +} + +void main(){ + int a = 12.0; + assert(a/test() == 2.0); +} +""" +) + +test("float 25", +""" +int main(){ + float a = 1.0; + float b = 2.0; + float c = 3.0; + assert(a + b + c == 6.0); + return 0; +} + +""") + +test("float 26", +""" +int main(){ + float a = 1.0; + float b = 2.0; + float c = 3.0; + assert(a - b - c == -4.0); + return 0; +} + +""") + +test("float 27", +""" +int main(){ + float a = 1.0; + float b = 2.0; + float c = 3.0; + assert(a - (b - c) == 2.0); + return 0; +} + +""") + +test("float 28", +""" +int main(){ + float a = 1.0; + float b = 2.0; + float c = 3.0; + assert(a * b * c == 6.0); + return 0; +} + +""") + +test("float 29", +""" +int main(){ + float a = 1.0; + float b = 2.0; + float c = 4.0; + assert(a/b/c == 0.125); + return 0; +} + +""") + +test("float 30", +""" +int main(){ + float a = 1.0; + float b = 2.0; + assert(a - - b == 3.0); + return 0; +} + +""") + +test("struct_size 1", +""" + +typedef struct {int a; int b;} mystruct; + +void main(){ + assert(sizeof mystruct == 4); +} +""" +) + +test("struct_size 2", +""" + +typedef struct {long int a; int b;} mystruct; + +void main(){ + assert(sizeof mystruct == 6); +} +""" +) + +test("struct_size 3", +""" + +typedef struct {long int a; int b;} struct_1; +typedef struct {long int a; struct_1 b;} mystruct; + +void main(){ + assert(sizeof mystruct == 10); +} +""" +) + +test("struct_size 4", +""" + +typedef struct {long int a; int b[2];} mystruct; + +void main(){ + assert(sizeof mystruct == 6); +} +""" +) + +test("struct_passing 1", +""" + +typedef struct {int a; int b;} mystruct; + +void test(mystruct mine){ + assert(mine.a == 1); + assert(mine.b == 2); +} + +void main(){ + mystruct an; + an.a = 1; + an.b = 2; + test(an); +} +""" +) + +test("struct_passing 2", +""" + +typedef struct {long int a; int b;} struct_1; +typedef struct {long int a; struct_1 b;} mystruct; + +void test(mystruct my){ + assert(my.a == 1); + assert(my.b.a == 2); + assert(my.b.b == 3); +} + +void main(){ + mystruct blah; + blah.a = 1; + blah.b.a = 2; + blah.b.b = 3; + test(blah); +} +""" +) + +test("struct_passing 3", +""" + +typedef struct {long int a; int b[10];} struct_1; +typedef struct {long int a; struct_1 b;} mystruct; + +void test(mystruct my){ + assert(my.a == 1); + assert(my.b.a == 2); + assert(my.b.b[0] == 3); +} + +void main(){ + mystruct blah; + blah.a = 1; + blah.b.a = 2; + blah.b.b[0] = 3; + test(blah); +} +""" +) + +#test("struct_return 1", +#""" +# +#typedef struct {long int a; int b;} struct_1; +# +#struct_1 test(){ +# struct_1 my; +# my.a = 1; +# my.b = 2; +# return my; +#} +# +#void main(){ +# struct_1 blah; +# blah = test(); +# assert(blah.a == 1); +# assert(blah.b == 2); +#} +#""" +#) + +test("print 1", +""" +unsigned test[] = "Hello World!"; +unsigned i=0; +void stdout_put_char(unsigned value){ + assert(test[i] == value); + i++; +} +#include + +void main(){ + print_string("Hello World!"); +} +""" +) + +test("print 2", +""" +unsigned test[] = "12345"; +unsigned i=0; +void stdout_put_char(unsigned value){ + assert(test[i] == value); + i++; +} +#include + +void main(){ + print_decimal(12345); +} +""" +) + +test("print 3", +""" +unsigned test[] = "-1234"; +unsigned i=0; +void stdout_put_char(unsigned value){ + assert(test[i] == value); + i++; +} +#include + +void main(){ + print_decimal(-1234); +} +""" +) + +test("print 4", +""" +unsigned test[] = "-1"; +unsigned i=0; +void stdout_put_char(unsigned value){ + assert(test[i] == value); + i++; +} +#include + +void main(){ + print_decimal(-1); +} +""" +) + +test("print 5", +""" +unsigned test[] = "7fff"; +unsigned i=0; +void stdout_put_char(unsigned value){ + assert(test[i] == value); + i++; +} +#include + +void main(){ + print_hex(0x7fff); +} +""" +) + +test("print 6", +""" +unsigned test[] = "ffff"; +unsigned i=0; +void stdout_put_char(unsigned value){ + assert(test[i] == value); + i++; +} +#include + +void main(){ + print_uhex(0xffffu); +} +""" +) + test("unsigned divide 1", """ void main(){ @@ -2823,6 +3584,29 @@ return 0; } """) + +test_fails("error 12", +""" + +typedef struct {long int a; int b;} struct_1; +typedef struct {long int a; struct_1 b;} mystruct; + +void test(mystruct my){ + assert(mystruct.a == 1); + assert(mystruct.b.a == 2); + assert(mystruct.b.b == 3); +} + +void main(){ + mystruct blah; + blah.a = 1; + blah.b.a = 2; + blah.b.b = 3; + test(blah); +} +""" +) + test("input 1", """ int main(){ @@ -2880,8 +3664,8 @@ } """) -os.system("python-coverage run -p c2verilog.py") +os.system("python-coverage run -p ../c2verilog") os.system("python-coverage combine") os.system("python-coverage report") -os.system("python-coverage annotate c2verilog.py") -os.system("python-coverage annotate compiler/parser.py") +os.system("python-coverage annotate ../c2verilog") +os.system("python-coverage annotate ../chips/compiler/parser.py")
/docs/source/chips.ico
0,0 → 1,730
 
 
 
<!DOCTYPE html>
<html>
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#">
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Chips-2.0/_static/chips.ico at gh-pages · dawsonjon/Chips-2.0</title>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" />
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub" />
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-114.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-144.png" />
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144.png" />
<link rel="logo" type="image/svg" href="https://github-media-downloads.s3.amazonaws.com/github-logo.svg" />
<meta property="og:image" content="https://github.global.ssl.fastly.net/images/modules/logos_page/Octocat.png">
<meta name="hostname" content="github-fe139-cp1-prd.iad.github.net">
<meta name="ruby" content="ruby 1.9.3p194-tcs-github-tcmalloc (e1c0c3f392) [x86_64-linux]">
<link rel="assets" href="https://github.global.ssl.fastly.net/">
<link rel="conduit-xhr" href="https://ghconduit.com:25035/">
<link rel="xhr-socket" href="/_sockets" />
 
 
<meta name="msapplication-TileImage" content="/windows-tile.png" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="selected-link" value="repo_source" data-pjax-transient />
<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="collector-cdn.github.com" name="octolytics-script-host" /><meta content="github" name="octolytics-app-id" /><meta content="520D2F61:32CA:20B44D0:52B873E7" name="octolytics-dimension-request_id" /><meta content="717535" name="octolytics-actor-id" /><meta content="dawsonjon" name="octolytics-actor-login" /><meta content="2ff1153d6d666ca91e92d701b1fb58b01ffb8c8a891ad44cc41ebfa85ac95aab" name="octolytics-actor-hash" />
 
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
 
<meta content="authenticity_token" name="csrf-param" />
<meta content="YcE43fnt6LSKvnjDdM54xMYoFKdEf/ZTE5/vk6KACPw=" name="csrf-token" />
 
<link href="https://github.global.ssl.fastly.net/assets/github-8f6ca9b17ae3eba1e30276eef0a16282cb651c78.css" media="all" rel="stylesheet" type="text/css" />
<link href="https://github.global.ssl.fastly.net/assets/github2-7ac593afddcc7532d8340dcde39be16c8cb6f732.css" media="all" rel="stylesheet" type="text/css" />
 
 
<script src="https://github.global.ssl.fastly.net/assets/frameworks-29a3fb0547e33bd8d4530bbad9bae3ef00d83293.js" type="text/javascript"></script>
<script src="https://github.global.ssl.fastly.net/assets/github-0b6bf4a8bb8bc8246eb6d07db6a63cde130f5001.js" type="text/javascript"></script>
<meta http-equiv="x-pjax-version" content="25e9435426189c5ffea9ed5e7a16f621">
 
<link data-pjax-transient rel='permalink' href='/dawsonjon/Chips-2.0/blob/f9da78eb03867a1fd09630fb82a8b9706bb2f2ae/_static/chips.ico'>
<meta property="og:title" content="Chips-2.0"/>
<meta property="og:type" content="githubog:gitrepository"/>
<meta property="og:url" content="https://github.com/dawsonjon/Chips-2.0"/>
<meta property="og:image" content="https://github.global.ssl.fastly.net/images/gravatars/gravatar-user-420.png"/>
<meta property="og:site_name" content="GitHub"/>
<meta property="og:description" content="Chips-2.0 - FPGA Design Suite featuring a component library, schematic entry, and C to Verilog design flow."/>
 
<meta name="description" content="Chips-2.0 - FPGA Design Suite featuring a component library, schematic entry, and C to Verilog design flow." />
 
<meta content="717535" name="octolytics-dimension-user_id" /><meta content="dawsonjon" name="octolytics-dimension-user_login" /><meta content="2855206" name="octolytics-dimension-repository_id" /><meta content="dawsonjon/Chips-2.0" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="2855206" name="octolytics-dimension-repository_network_root_id" /><meta content="dawsonjon/Chips-2.0" name="octolytics-dimension-repository_network_root_nwo" />
<link href="https://github.com/dawsonjon/Chips-2.0/commits/gh-pages.atom" rel="alternate" title="Recent Commits to Chips-2.0:gh-pages" type="application/atom+xml" />
 
</head>
 
 
<body class="logged_in env-production linux vis-public page-blob">
<div class="wrapper">
 
 
<div class="header header-logged-in true">
<div class="container clearfix">
 
<a class="header-logo-invertocat" href="https://github.com/">
<span class="mega-octicon octicon-mark-github"></span>
</a>
 
<a href="/notifications" class="notification-indicator tooltipped downwards" data-gotokey="n" title="You have no unread notifications">
<span class="mail-status all-read"></span>
</a>
 
<div class="command-bar js-command-bar in-repository">
<form accept-charset="UTF-8" action="/search" class="command-bar-form" id="top_search_form" method="get">
 
<input type="text" data-hotkey="/ s" name="q" id="js-command-bar-field" placeholder="Search or type a command" tabindex="1" autocapitalize="off"
data-username="dawsonjon"
data-repo="dawsonjon/Chips-2.0"
data-branch="gh-pages"
data-sha="153846a266dd1b7342fdc77b922e8854ba5bb062"
>
 
<input type="hidden" name="nwo" value="dawsonjon/Chips-2.0" />
 
<div class="select-menu js-menu-container js-select-menu search-context-select-menu">
<span class="minibutton select-menu-button js-menu-target">
<span class="js-select-button">This repository</span>
</span>
 
<div class="select-menu-modal-holder js-menu-content js-navigation-container">
<div class="select-menu-modal">
 
<div class="select-menu-item js-navigation-item js-this-repository-navigation-item selected">
<span class="select-menu-item-icon octicon octicon-check"></span>
<input type="radio" class="js-search-this-repository" name="search_target" value="repository" checked="checked" />
<div class="select-menu-item-text js-select-button-text">This repository</div>
</div> <!-- /.select-menu-item -->
 
<div class="select-menu-item js-navigation-item js-all-repositories-navigation-item">
<span class="select-menu-item-icon octicon octicon-check"></span>
<input type="radio" name="search_target" value="global" />
<div class="select-menu-item-text js-select-button-text">All repositories</div>
</div> <!-- /.select-menu-item -->
 
</div>
</div>
</div>
 
<span class="octicon help tooltipped downwards" title="Show command bar help">
<span class="octicon octicon-question"></span>
</span>
 
 
<input type="hidden" name="ref" value="cmdform">
 
</form>
<ul class="top-nav">
<li class="explore"><a href="/explore">Explore</a></li>
<li><a href="https://gist.github.com">Gist</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="https://help.github.com">Help</a></li>
</ul>
</div>
 
 
 
<ul id="user-links">
<li>
<a href="/dawsonjon" class="name">
<img height="20" src="https://1.gravatar.com/avatar/98ce35eb2c038b237b5b66fe9d5e0123?d=https%3A%2F%2Fidenticons.github.com%2F7aaf894aa84d0d95dcfe1518ef1ff150.png&amp;r=x&amp;s=140" width="20" /> dawsonjon
</a>
</li>
 
<li>
<a href="/new" id="new_repo" class="tooltipped downwards" title="Create a new repo" aria-label="Create a new repo">
<span class="octicon octicon-repo-create"></span>
</a>
</li>
 
<li>
<a href="/settings/profile" id="account_settings"
class="tooltipped downwards"
aria-label="Account settings "
title="Account settings ">
<span class="octicon octicon-tools"></span>
</a>
</li>
<li>
<a class="tooltipped downwards" href="/logout" data-method="post" id="logout" title="Sign out" aria-label="Sign out">
<span class="octicon octicon-log-out"></span>
</a>
</li>
 
</ul>
 
<div class="js-new-dropdown-contents hidden">
 
<ul class="dropdown-menu">
<li>
<a href="/new"><span class="octicon octicon-repo-create"></span> New repository</a>
</li>
<li>
<a href="/organizations/new"><span class="octicon octicon-organization"></span> New organization</a>
</li>
 
 
 
<li class="section-title">
<span title="dawsonjon/Chips-2.0">This repository</span>
</li>
<li>
<a href="/dawsonjon/Chips-2.0/issues/new"><span class="octicon octicon-issue-opened"></span> New issue</a>
</li>
<li>
<a href="/dawsonjon/Chips-2.0/settings/collaboration"><span class="octicon octicon-person-add"></span> New collaborator</a>
</li>
</ul>
 
</div>
 
 
</div>
</div>
 
 
 
 
 
 
<div class="site" itemscope itemtype="http://schema.org/WebPage">
<div class="pagehead repohead instapaper_ignore readability-menu">
<div class="container">
 
<ul class="pagehead-actions">
 
<li class="subscription">
<form accept-charset="UTF-8" action="/notifications/subscribe" class="js-social-container" data-autosubmit="true" data-remote="true" method="post"><div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="YcE43fnt6LSKvnjDdM54xMYoFKdEf/ZTE5/vk6KACPw=" /></div> <input id="repository_id" name="repository_id" type="hidden" value="2855206" />
 
<div class="select-menu js-menu-container js-select-menu">
<a class="social-count js-social-count" href="/dawsonjon/Chips-2.0/watchers">
2
</a>
<span class="minibutton select-menu-button with-count js-menu-target" role="button" tabindex="0">
<span class="js-select-button">
<span class="octicon octicon-eye-unwatch"></span>
Unwatch
</span>
</span>
 
<div class="select-menu-modal-holder">
<div class="select-menu-modal subscription-menu-modal js-menu-content">
<div class="select-menu-header">
<span class="select-menu-title">Notification status</span>
<span class="octicon octicon-remove-close js-menu-close"></span>
</div> <!-- /.select-menu-header -->
 
<div class="select-menu-list js-navigation-container" role="menu">
 
<div class="select-menu-item js-navigation-item " role="menuitem" tabindex="0">
<span class="select-menu-item-icon octicon octicon-check"></span>
<div class="select-menu-item-text">
<input id="do_included" name="do" type="radio" value="included" />
<h4>Not watching</h4>
<span class="description">You only receive notifications for conversations in which you participate or are @mentioned.</span>
<span class="js-select-button-text hidden-select-button-text">
<span class="octicon octicon-eye-watch"></span>
Watch
</span>
</div>
</div> <!-- /.select-menu-item -->
 
<div class="select-menu-item js-navigation-item selected" role="menuitem" tabindex="0">
<span class="select-menu-item-icon octicon octicon octicon-check"></span>
<div class="select-menu-item-text">
<input checked="checked" id="do_subscribed" name="do" type="radio" value="subscribed" />
<h4>Watching</h4>
<span class="description">You receive notifications for all conversations in this repository.</span>
<span class="js-select-button-text hidden-select-button-text">
<span class="octicon octicon-eye-unwatch"></span>
Unwatch
</span>
</div>
</div> <!-- /.select-menu-item -->
 
<div class="select-menu-item js-navigation-item " role="menuitem" tabindex="0">
<span class="select-menu-item-icon octicon octicon-check"></span>
<div class="select-menu-item-text">
<input id="do_ignore" name="do" type="radio" value="ignore" />
<h4>Ignoring</h4>
<span class="description">You do not receive any notifications for conversations in this repository.</span>
<span class="js-select-button-text hidden-select-button-text">
<span class="octicon octicon-mute"></span>
Stop ignoring
</span>
</div>
</div> <!-- /.select-menu-item -->
 
</div> <!-- /.select-menu-list -->
 
</div> <!-- /.select-menu-modal -->
</div> <!-- /.select-menu-modal-holder -->
</div> <!-- /.select-menu -->
 
</form>
</li>
 
<li>
 
<div class="js-toggler-container js-social-container starring-container on">
<a href="/dawsonjon/Chips-2.0/unstar"
class="minibutton with-count js-toggler-target star-button starred upwards"
title="Unstar this repository" data-remote="true" data-method="post" rel="nofollow">
<span class="octicon octicon-star-delete"></span><span class="text">Unstar</span>
</a>
 
<a href="/dawsonjon/Chips-2.0/star"
class="minibutton with-count js-toggler-target star-button unstarred upwards"
title="Star this repository" data-remote="true" data-method="post" rel="nofollow">
<span class="octicon octicon-star"></span><span class="text">Star</span>
</a>
 
<a class="social-count js-social-count" href="/dawsonjon/Chips-2.0/stargazers">
2
</a>
</div>
 
</li>
 
 
<li>
<a href="/dawsonjon/Chips-2.0/fork" class="minibutton with-count js-toggler-target fork-button lighter upwards" title="Fork this repo" rel="nofollow" data-method="post">
<span class="octicon octicon-git-branch-create"></span><span class="text">Fork</span>
</a>
<a href="/dawsonjon/Chips-2.0/network" class="social-count">1</a>
</li>
 
 
</ul>
 
<h1 itemscope itemtype="http://data-vocabulary.org/Breadcrumb" class="entry-title public">
<span class="repo-label"><span>public</span></span>
<span class="mega-octicon octicon-repo"></span>
<span class="author">
<a href="/dawsonjon" class="url fn" itemprop="url" rel="author"><span itemprop="title">dawsonjon</span></a>
</span>
<span class="repohead-name-divider">/</span>
<strong><a href="/dawsonjon/Chips-2.0" class="js-current-repository js-repo-home-link">Chips-2.0</a></strong>
 
<span class="page-context-loader">
<img alt="Octocat-spinner-32" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</span>
 
</h1>
</div><!-- /.container -->
</div><!-- /.repohead -->
 
<div class="container">
 
<div class="repository-with-sidebar repo-container ">
 
<div class="repository-sidebar">
 
<div class="sunken-menu vertical-right repo-nav js-repo-nav js-repository-container-pjax js-octicon-loaders">
<div class="sunken-menu-contents">
<ul class="sunken-menu-group">
<li class="tooltipped leftwards" title="Code">
<a href="/dawsonjon/Chips-2.0/tree/gh-pages" aria-label="Code" class="selected js-selected-navigation-item sunken-menu-item" data-gotokey="c" data-pjax="true" data-selected-links="repo_source repo_downloads repo_commits repo_tags repo_branches /dawsonjon/Chips-2.0/tree/gh-pages">
<span class="octicon octicon-code"></span> <span class="full-word">Code</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
 
<li class="tooltipped leftwards" title="Issues">
<a href="/dawsonjon/Chips-2.0/issues" aria-label="Issues" class="js-selected-navigation-item sunken-menu-item js-disable-pjax" data-gotokey="i" data-selected-links="repo_issues /dawsonjon/Chips-2.0/issues">
<span class="octicon octicon-issue-opened"></span> <span class="full-word">Issues</span>
<span class='counter'>17</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
 
<li class="tooltipped leftwards" title="Pull Requests">
<a href="/dawsonjon/Chips-2.0/pulls" aria-label="Pull Requests" class="js-selected-navigation-item sunken-menu-item js-disable-pjax" data-gotokey="p" data-selected-links="repo_pulls /dawsonjon/Chips-2.0/pulls">
<span class="octicon octicon-git-pull-request"></span> <span class="full-word">Pull Requests</span>
<span class='counter'>0</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
 
 
<li class="tooltipped leftwards" title="Wiki">
<a href="/dawsonjon/Chips-2.0/wiki" aria-label="Wiki" class="js-selected-navigation-item sunken-menu-item" data-pjax="true" data-selected-links="repo_wiki /dawsonjon/Chips-2.0/wiki">
<span class="octicon octicon-book"></span> <span class="full-word">Wiki</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
</ul>
<div class="sunken-menu-separator"></div>
<ul class="sunken-menu-group">
 
<li class="tooltipped leftwards" title="Pulse">
<a href="/dawsonjon/Chips-2.0/pulse" aria-label="Pulse" class="js-selected-navigation-item sunken-menu-item" data-pjax="true" data-selected-links="pulse /dawsonjon/Chips-2.0/pulse">
<span class="octicon octicon-pulse"></span> <span class="full-word">Pulse</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
 
<li class="tooltipped leftwards" title="Graphs">
<a href="/dawsonjon/Chips-2.0/graphs" aria-label="Graphs" class="js-selected-navigation-item sunken-menu-item" data-pjax="true" data-selected-links="repo_graphs repo_contributors /dawsonjon/Chips-2.0/graphs">
<span class="octicon octicon-graph"></span> <span class="full-word">Graphs</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
 
<li class="tooltipped leftwards" title="Network">
<a href="/dawsonjon/Chips-2.0/network" aria-label="Network" class="js-selected-navigation-item sunken-menu-item js-disable-pjax" data-selected-links="repo_network /dawsonjon/Chips-2.0/network">
<span class="octicon octicon-git-branch"></span> <span class="full-word">Network</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a> </li>
</ul>
 
 
<div class="sunken-menu-separator"></div>
<ul class="sunken-menu-group">
<li class="tooltipped leftwards" title="Settings">
<a href="/dawsonjon/Chips-2.0/settings"
class="sunken-menu-item" data-pjax aria-label="Settings">
<span class="octicon octicon-tools"></span> <span class="full-word">Settings</span>
<img alt="Octocat-spinner-32" class="mini-loader" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32.gif" width="16" />
</a>
</li>
</ul>
</div>
</div>
 
<div class="only-with-full-nav">
 
 
<div class="clone-url open"
data-protocol-type="http"
data-url="/users/set_protocol?protocol_selector=http&amp;protocol_type=push">
<h3><strong>HTTPS</strong> clone URL</h3>
<div class="clone-url-box">
<input type="text" class="clone js-url-field"
value="https://github.com/dawsonjon/Chips-2.0.git" readonly="readonly">
 
<span class="js-zeroclipboard url-box-clippy minibutton zeroclipboard-button" data-clipboard-text="https://github.com/dawsonjon/Chips-2.0.git" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
 
 
<div class="clone-url "
data-protocol-type="ssh"
data-url="/users/set_protocol?protocol_selector=ssh&amp;protocol_type=push">
<h3><strong>SSH</strong> clone URL</h3>
<div class="clone-url-box">
<input type="text" class="clone js-url-field"
value="git@github.com:dawsonjon/Chips-2.0.git" readonly="readonly">
 
<span class="js-zeroclipboard url-box-clippy minibutton zeroclipboard-button" data-clipboard-text="git@github.com:dawsonjon/Chips-2.0.git" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
 
 
<div class="clone-url "
data-protocol-type="subversion"
data-url="/users/set_protocol?protocol_selector=subversion&amp;protocol_type=push">
<h3><strong>Subversion</strong> checkout URL</h3>
<div class="clone-url-box">
<input type="text" class="clone js-url-field"
value="https://github.com/dawsonjon/Chips-2.0" readonly="readonly">
 
<span class="js-zeroclipboard url-box-clippy minibutton zeroclipboard-button" data-clipboard-text="https://github.com/dawsonjon/Chips-2.0" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
 
 
<p class="clone-options">You can clone with
<a href="#" class="js-clone-selector" data-protocol="http">HTTPS</a>,
<a href="#" class="js-clone-selector" data-protocol="ssh">SSH</a>,
or <a href="#" class="js-clone-selector" data-protocol="subversion">Subversion</a>.
<span class="octicon help tooltipped upwards" title="Get help on which URL is right for you.">
<a href="https://help.github.com/articles/which-remote-url-should-i-use">
<span class="octicon octicon-question"></span>
</a>
</span>
</p>
 
 
 
<a href="/dawsonjon/Chips-2.0/archive/gh-pages.zip"
class="minibutton sidebar-button"
title="Download this repository as a zip file"
rel="nofollow">
<span class="octicon octicon-cloud-download"></span>
Download ZIP
</a>
</div>
</div><!-- /.repository-sidebar -->
 
<div id="js-repo-pjax-container" class="repository-content context-loader-container" data-pjax-container>
 
 
<!-- blob contrib key: blob_contributors:v21:b7c60da2fdeae3f0b0c0d3ddfeedd4a9 -->
 
<p title="This is a placeholder element" class="js-history-link-replace hidden"></p>
 
<a href="/dawsonjon/Chips-2.0/find/gh-pages" data-pjax data-hotkey="t" class="js-show-file-finder" style="display:none">Show File Finder</a>
 
<div class="file-navigation">
 
<div class="select-menu js-menu-container js-select-menu" >
<span class="minibutton select-menu-button js-menu-target" data-hotkey="w"
data-master-branch="master"
data-ref="gh-pages"
role="button" aria-label="Switch branches or tags" tabindex="0">
<span class="octicon octicon-git-branch"></span>
<i>branch:</i>
<span class="js-select-button">gh-pages</span>
</span>
 
<div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax>
 
<div class="select-menu-modal">
<div class="select-menu-header">
<span class="select-menu-title">Switch branches/tags</span>
<span class="octicon octicon-remove-close js-menu-close"></span>
</div> <!-- /.select-menu-header -->
 
<div class="select-menu-filters">
<div class="select-menu-text-filter">
<input type="text" aria-label="Find or create a branch…" id="context-commitish-filter-field" class="js-filterable-field js-navigation-enable" placeholder="Find or create a branch…">
</div>
<div class="select-menu-tabs">
<ul>
<li class="select-menu-tab">
<a href="#" data-tab-filter="branches" class="js-select-menu-tab">Branches</a>
</li>
<li class="select-menu-tab">
<a href="#" data-tab-filter="tags" class="js-select-menu-tab">Tags</a>
</li>
</ul>
</div><!-- /.select-menu-tabs -->
</div><!-- /.select-menu-filters -->
 
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches">
 
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
 
 
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/dawsonjon/Chips-2.0/blob/examples/_static/chips.ico"
data-name="examples"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="examples">examples</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item selected">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/dawsonjon/Chips-2.0/blob/gh-pages/_static/chips.ico"
data-name="gh-pages"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="gh-pages">gh-pages</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/dawsonjon/Chips-2.0/blob/master/_static/chips.ico"
data-name="master"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="master">master</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/dawsonjon/Chips-2.0/blob/non-gui/_static/chips.ico"
data-name="non-gui"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="non-gui">non-gui</a>
</div> <!-- /.select-menu-item -->
<div class="select-menu-item js-navigation-item ">
<span class="select-menu-item-icon octicon octicon-check"></span>
<a href="/dawsonjon/Chips-2.0/blob/optimizer/_static/chips.ico"
data-name="optimizer"
data-skip-pjax="true"
rel="nofollow"
class="js-navigation-open select-menu-item-text js-select-button-text css-truncate-target"
title="optimizer">optimizer</a>
</div> <!-- /.select-menu-item -->
</div>
 
<form accept-charset="UTF-8" action="/dawsonjon/Chips-2.0/branches" class="js-create-branch select-menu-item select-menu-new-item-form js-navigation-item js-new-item-form" method="post"><div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="YcE43fnt6LSKvnjDdM54xMYoFKdEf/ZTE5/vk6KACPw=" /></div>
<span class="octicon octicon-git-branch-create select-menu-item-icon"></span>
<div class="select-menu-item-text">
<h4>Create branch: <span class="js-new-item-name"></span></h4>
<span class="description">from ‘gh-pages’</span>
</div>
<input type="hidden" name="name" id="name" class="js-new-item-value">
<input type="hidden" name="branch" id="branch" value="gh-pages" />
<input type="hidden" name="path" id="path" value="_static/chips.ico" />
</form> <!-- /.select-menu-item -->
 
</div> <!-- /.select-menu-list -->
 
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
 
 
</div>
 
<div class="select-menu-no-results">Nothing to show</div>
</div> <!-- /.select-menu-list -->
 
</div> <!-- /.select-menu-modal -->
</div> <!-- /.select-menu-modal-holder -->
</div> <!-- /.select-menu -->
 
<div class="breadcrumb">
<span class='repo-root js-repo-root'><span itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb"><a href="/dawsonjon/Chips-2.0/tree/gh-pages" data-branch="gh-pages" data-direction="back" data-pjax="true" itemscope="url"><span itemprop="title">Chips-2.0</span></a></span></span><span class="separator"> / </span><span itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb"><a href="/dawsonjon/Chips-2.0/tree/gh-pages/_static" data-branch="gh-pages" data-direction="back" data-pjax="true" itemscope="url"><span itemprop="title">_static</span></a></span><span class="separator"> / </span><strong class="final-path">chips.ico</strong> <span class="js-zeroclipboard minibutton zeroclipboard-button" data-clipboard-text="_static/chips.ico" data-copied-hint="copied!" title="copy to clipboard"><span class="octicon octicon-clippy"></span></span>
</div>
</div>
 
 
<div class="commit commit-loader file-history-tease js-deferred-content" data-url="/dawsonjon/Chips-2.0/contributors/gh-pages/_static/chips.ico">
Fetching contributors…
 
<div class="participation">
<p class="loader-loading"><img alt="Octocat-spinner-32-eaf2f5" height="16" src="https://github.global.ssl.fastly.net/images/spinners/octocat-spinner-32-EAF2F5.gif" width="16" /></p>
<p class="loader-error">Cannot retrieve contributors at this time</p>
</div>
</div>
 
<div id="files" class="bubble">
<div class="file">
<div class="meta">
<div class="info">
<span class="icon"><b class="octicon octicon-file-text"></b></span>
<span class="mode" title="File Mode">file</span>
<span>4.286 kb</span>
</div>
<div class="actions">
<div class="button-group">
<a href="/dawsonjon/Chips-2.0/raw/gh-pages/_static/chips.ico" class="button minibutton " id="raw-url">Raw</a>
<a href="/dawsonjon/Chips-2.0/commits/gh-pages/_static/chips.ico" class="button minibutton " rel="nofollow">History</a>
</div><!-- /.button-group -->
<a class="minibutton danger empty-icon tooltipped downwards"
href="/dawsonjon/Chips-2.0/delete/gh-pages/_static/chips.ico"
title=""
data-method="post" data-test-id="delete-blob-file" rel="nofollow">
Delete
</a>
</div><!-- /.actions -->
 
</div>
<div class="blob-wrapper data type-text js-blob-data">
<div class="image js-image">
<a href="/dawsonjon/Chips-2.0/blob/gh-pages/_static/chips.ico?raw=true">View Raw</a>
</div>
</div>
 
</div>
</div>
 
<a href="#jump-to-line" rel="facebox[.linejump]" data-hotkey="l" class="js-jump-to-line" style="display:none">Jump to Line</a>
<div id="jump-to-line" style="display:none">
<form accept-charset="UTF-8" class="js-jump-to-line-form">
<input class="linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line&hellip;" autofocus>
<button type="submit" class="button">Go</button>
</form>
</div>
 
</div>
 
</div><!-- /.repo-container -->
<div class="modal-backdrop"></div>
</div><!-- /.container -->
</div><!-- /.site -->
 
 
</div><!-- /.wrapper -->
 
<div class="container">
<div class="site-footer">
<ul class="site-footer-links right">
<li><a href="https://status.github.com/">Status</a></li>
<li><a href="http://developer.github.com">API</a></li>
<li><a href="http://training.github.com">Training</a></li>
<li><a href="http://shop.github.com">Shop</a></li>
<li><a href="/blog">Blog</a></li>
<li><a href="/about">About</a></li>
 
</ul>
 
<a href="/">
<span class="mega-octicon octicon-mark-github"></span>
</a>
 
<ul class="site-footer-links">
<li>&copy; 2013 <span title="0.04100s from github-fe139-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
<li><a href="/site/terms">Terms</a></li>
<li><a href="/site/privacy">Privacy</a></li>
<li><a href="/security">Security</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div><!-- /.site-footer -->
</div><!-- /.container -->
 
 
<div class="fullscreen-overlay js-fullscreen-overlay" id="fullscreen_overlay">
<div class="fullscreen-container js-fullscreen-container">
<div class="textarea-wrap">
<textarea name="fullscreen-contents" id="fullscreen-contents" class="js-fullscreen-contents" placeholder="" data-suggester="fullscreen_suggester"></textarea>
<div class="suggester-container">
<div class="suggester fullscreen-suggester js-navigation-container" id="fullscreen_suggester"
data-url="/dawsonjon/Chips-2.0/suggestions/commit">
</div>
</div>
</div>
</div>
<div class="fullscreen-sidebar">
<a href="#" class="exit-fullscreen js-exit-fullscreen tooltipped leftwards" title="Exit Zen Mode">
<span class="mega-octicon octicon-screen-normal"></span>
</a>
<a href="#" class="theme-switcher js-theme-switcher tooltipped leftwards"
title="Switch themes">
<span class="octicon octicon-color-mode"></span>
</a>
</div>
</div>
 
 
 
<div id="ajax-error-message" class="flash flash-error">
<span class="octicon octicon-alert"></span>
<a href="#" class="octicon octicon-remove-close close ajax-error-dismiss"></a>
Something went wrong with that request. Please try again.
</div>
 
</body>
</html>
 
/docs/source/language_reference/index.rst
0,0 → 1,542
===============================
Reference Manual
===============================
 
Download
========
 
You can download the
`source <https://github.com/dawsonjon/Chips-2.0/archive/master.zip>`_
from the
`Git Hub <https://github.com/dawsonjon/Chips-2.0>`_
homepage. Alternatively clone the project using git::
 
~$ git clone https://github.com/dawsonjon/Chips-2.0.git
 
 
Install
=======
 
1. First `install Python <http://python.org/download>`_. You need *Python* 2.6 or later, but not *Python* 3.
2. In the Linux console, or the Windows command line (you will need
administrator privileges)::
 
~$ cd Chips-2.0
~$ python setup.py install
 
Icarus Verilog
==============
 
This example uses the `Icarus Verilog <http://iverilog.icarus.com/>`_
simulator, you will need this installed in your command path to follow this
tutorial.
 
C Components
============
 
This section of the manual describes the subset of the C language that is available in *Chips*.
 
Types
-----
 
The following types are available in chips:
 
+ `char`
+ `int`
+ `long`
+ `unsigned char`
+ `unsigned int`
+ `unsigned long`
+ `float`
 
A `char` is at least 8 bits wide. An `int` is at least 16 bits wide. A `long`
is at least 32 bits wide.
 
The `float` type is implemented as an IEEE 754 single precision floating point
number.
 
At present, `long long`, `float` and `double` have not been implemented, but I
plan to add support for these types in a later release.
 
single dimensional arrays, `char[]`, `int[]` and `long[]` are supported, but
multidimensional arrays are not yet supported.
 
`struct` s are supported, you can define arrays of `struct` s, and `struct` s
may contain arrays.
 
`struct` s cannot yet be passed to a function or returned from a function.
 
Arrays may be passed (by reference) to functions.
 
Pointers are not supported, and neither is dynamic memory allocation. This is a
deliberate decision with low memory FPGAs in mind, and probably won't be
supported in future releases.
 
Functions
---------
 
Functions are supported. They may be nested, but may not be recursive. Only a
fixed number of arguments is supported, optional arguments are not permitted.
 
Control Structures
------------------
 
The following control structures are supported:
 
+ if/else statements
+ while loop
+ for loop
+ break/continue statements
+ switch/case statements
 
Operators
---------
 
The following operators are supported, in order of preference:
 
+ `()`
+ `~` `-` `!` `sizeof` (unary operators)
+ `*` `/` `%`
+ `+` `-`
+ `<<` `>>`
+ `<` `>` `<=` `>=`
+ `==` `!=`
+ `&`
+ '^`
+ `|`
+ `&&`
+ `||`
+ \`? : `
 
 
Stream I/O
----------
 
The language has been extended to allow components to communicate by sending
data through streams.
 
Stream I/O is achieved by calling built-in functions with special names.
Functions that start with the name `input` or `output` are interpreted as "read
from input", or "write to output".
 
.. code-block:: c
 
int temp;
temp = input_spam(); //reads from an input called spam
temp = input_eggs(); //reads from an input called eggs
output_fish(temp); //writes to an output called fish
 
Reading or writing from inputs and outputs causes program execution to block
until data is available. If you don't want to commit yourself to reading and
input and blocking execution, you can check if data is ready.
 
.. code-block:: c
 
int temp;
if(ready_spam()){
temp = input_spam();
}
 
There is no equivalent function to check if an output is ready to receive data,
this could cause deadlocks if both the sending and receiving end were waiting
for one another.
 
Timed Waits
-----------
 
Timed waits can be achieved using the built-in `wait-clocks` function. The
wait_clocks function accepts a single argument, the numbers of clock cycles to
wait.
 
.. code-block:: c
wait_clocks(100); //wait for 1 us with 100MHz clock
 
 
Debug and Test
--------------
 
The built in `report` function displays the value of an expression in the
simulation console. This will have no effect in a synthesised design.
 
.. code-block:: c
 
int temp = 4;
report(temp); //prints 4 to console
report(10); //prints 10 to the console
 
 
The built in function assert causes a simulation error if it is passed a zero
value. The assert function has no effect in a synthesised design.
 
.. code-block:: c
 
int temp = 5;
assert(temp); //does not cause an error
int temp = 0;
assert(temp); //will cause a simulation error
assert(2+2==5); //will cause a simulation error
 
In simulation, you can write values to a file using the built-in `file_write`
function. The first argument is the value to write, and the second argument is
the file to write to. The file will be overwritten when the simulation starts,
and subsequent calls will append a new vale to the end of the file. Each value
will appear in decimal format on a separate line. A file write has no effect in
a synthesised design.
 
.. code-block:: c
 
file_write(1, "simulation_log.txt");
file_write(2, "simulation_log.txt");
file_write(3, "simulation_log.txt");
file_write(4, "simulation_log.txt");
 
You can also read values from a file during simulation. A simulation error will
occur if there are no more value in the file.
 
.. code-block:: c
 
assert(file_read("simulation_log.txt") == 1);
assert(file_read("simulation_log.txt") == 2);
assert(file_read("simulation_log.txt") == 3);
assert(file_read("simulation_log.txt") == 4);
 
 
C Preprocessor
--------------
 
The C preprocessor currently has only limited capabilities, and currently only
the `#include` feature is supported.
 
Built in Libraries
==================
 
The C standard library is not supported. The intention is to provide a build-in
library with some basic utilities appropriate for FPGA design. At present
`print.h` is the only library provided.
 
print.h
-------
 
The `print_string` function prints a null terminated string to standard output.
 
.. code-block:: c
 
void print_string(char string[])
 
The `print_decimal` function prints a number in decimal to standard output.
 
.. code-block:: c
 
void print_decimal(int value)
 
The `print_hex` function prints a number in hexadecimal format to standard output.
 
.. code-block:: c
 
void print_hex(int value)
 
To provide most flexibility, the definition of standard_output is left to the
user, it could be a serial port, an LCD display, or perhaps a telnet session.
To define standard output, a function `stdout_put_char` function must be
defined before including print.h.
 
.. code-block:: c
 
void stdout_put_char(char value){
output_rs232_tx(value);
}
 
#include <print.h>
 
print_string("Hello World!\n"); //Hello World
print_decimal(12345); //12345
print_hex(127); //0x7f
 
c2verilog
---------
 
For simple designs with only one C component, the simplest way to generate Verilog is by using the c2verilog utility.
The utility accepts C files as input, and generates Verilog files as output.
 
::
 
~$ c2verilog input_file.c
 
You may automatically compile the output using Icarus Verilog by adding the
`iverilog` option. You may also run the Icarus Verilog simulation using the
`run` option.
 
::
 
~$ c2verilog iverilog run input_file.c
 
You can also influence the way the Verilog is generated. By default, a low area
solution is implemented. If you can specify a design optimised for speed using
the `speed` option.
 
Python API
==========
 
The C language provides the ability to define components. The Python API
provides the ability to build systems from C components.
 
To use the Python API, you must import it.
 
.. code-block:: python
 
from chips.api.api import *
 
Chip
----
 
Once you have imported the Python API, you can define a chip. A chip is a
canvas to which you can add inputs outputs, components and wires. When you
create a chips all you need to give it is a name.
 
.. code-block:: python
 
mychip = Chip("mychip")
 
Wire
----
 
You can create `Input`, `Output` and `Wires` objects. A `Wire` is a point to point connection, a stream, that connects an output from one component to the input of another. A `Wire` can only have one source of data, and one data sink. When you create a `Wire`, you must tell it which `Chip` it belongs to:
 
.. code-block:: python
 
wire_a = Wire(mychip)
wire_b = Wire(mychip)
 
Input
-----
 
An `Input` takes data from outside the `Chip`, and feeds it into the input of a
`Component`. When you create an `Input`, you need to specify the `Chip` it
belongs to, and the name it will be given.
 
.. code-block:: python
 
input_a = Input(mychip, "A")
input_b = Input(mychip, "B")
input_c = Input(mychip, "C")
input_d = Input(mychip, "D")
 
Output
------
 
An `Output` takes data from a `Component` output, and sends it outside the
`Chip`. When you create an `Output` you must tell it which `Chip` it belongs
to, and the name it will be given.
 
Component
---------
 
From Python, you can import a C component by specifying the file where it is
defined. When you import a C component it will be compiled.
 
The C file adder.c defines a two input adder.
 
.. code-block:: python
 
//adder.c
 
void adder(){
while(1){
output_z(input_a() + input_b());
}
}
 
.. code-block:: python
 
adder = Component("source/adder.c")
 
Instances
---------
 
You can make many instances of a component by "calling" the component. Each
time you make an instance, you must specify the `Chip` it belongs to, and
connect up the inputs and outputs of the `Component`.
 
.. code-block:: python
adder(mychip,
inputs = {"a" : input_a, "b" : input_b},
outputs = {"z" : wire_a})
 
adder(mychip,
inputs = {"a" : input_c, "b" : input_d},
outputs = {"z" : wire_b})
 
adder(mychip,
inputs = {"a" : wire_a, "b" : wire_b},
outputs = {"z" : output_z})
 
A diagrammatic representation of the `Chip` is shown below.
 
::
 
+-------+ +-------+
| adder | | adder |
A =====> >=======> >=====> Z
B =====> | | |
+-------+ | |
| |
+-------+ | |
| adder | | |
C =====> >=======> |
D =====> | | |
+-------+ +-------+
 
Code Generation
---------------
 
You can generate synthesisable Verilog code for your chip
using the `generate_verilog` method.
 
.. code-block:: python
 
mychip.generate_verilog()
 
You can also generate a matching testbench using the `generate_testbench`
method. You can also specify the simulation run time in clock cycles.
 
.. code-block:: python
mychip.generate_testbench(1000) #1000 clocks
 
To compile the design in Icarus Verilog, use the `compile_iverilog` method. You
can also run the code directly if you pass `True` to the `compile_iverilog`
function.
.. code-block:: python
 
mychip.compile_iverilog(True)
 
 
Physical Interface
==================
 
`Input`, `Output` and `Wire` objects within a chip are implemented using a
synchronous interconnect bus. The details of the interconnect bus are described
here. This section will be of most use to developers who want to integrate a
*Chips* design into a larger design, or to generate an HDL wrapper to support a
*Chips* design in new hardware.
 
::
rst >-o-----------------------------+
clk >-+-o-------------------------+ |
| | | |
| | +-----------+ | | +--------------+
| | | TX | | | | RX |
| +---> | | +-----> |
+-----> | +-------> |
| | | |
| | <bus_name> | |
| out >=================> in |
| | <bus_name>_stb | |
| out >-----------------> in |
| | <bus_name>_ack | |
| in <-----------------< out |
| | | |
+-----------+ +--------------+
Global Signals
--------------
+------+-----------+------+-------------+
| Name | Direction | Type | Description |
+------+-----------+------+-------------+
| clk | input | bit | Clock |
+------+-----------+------+-------------+
| rst | input | bit | Reset |
+------+-----------+------+-------------+
 
Interconnect Signals
--------------------
 
+----------------+-----------+------+-----------------------------------------------------------+
| Name | Direction | Type | Description |
+----------------+-----------+------+-----------------------------------------------------------+
| <bus_name> | TX to RX | bus | Payload Data |
+----------------+-----------+------+-----------------------------------------------------------+
| <bus_name>_stb | TX to RX | bit | '1' indicates that payload data is valid and TX is ready. |
+----------------+-----------+------+-----------------------------------------------------------+
| <bus_name>_ack | TX to RX | bit | '1' indicates that RX is ready. |
+----------------+-----------+------+-----------------------------------------------------------+
 
Interconnect Bus Transaction
----------------------------
1. Both transmitter and receiver **shall** be synchronised to the 0 to 1 transition of `clk`.
#. If `rst` is set to 1, upon the 0 to 1 transition of `clk` the transmitter **shall** terminate any active bus transaction and set `<bus_name>_stb` to 0.
#. If `rst` is set to 1, upon the 0 to 1 transition of `clk` the receiver **shall** terminate any active bus transaction and set `<bus_name>_ack` to 0.
#. If `rst` is set to 0, normal operation **shall** commence.
#. The transmitter **may** insert wait states on the bus by setting `<bus_name>_stb` to 0.
#. The transmitter **shall** set `<bus_name>_stb` to 1 to signify that data is valid.
#. Once `<bus_name>_stb` has been set to 1, it **shall** remain at 1 until the transaction completes.
#. The transmitter **shall** ensure that `<bus_name>` contains valid data for the entire period that `<bus_name>_stb` is 1.
#. The transmitter **may** set `<bus_name>` to any value when `<bus_name>_stb` is 0.
#. The receiver **may** insert wait states on the bus by setting `<bus_name>_ack` to 0.
#. The receiver **shall** set `<bus_name>_ack` to 1 to signify that it is ready to receive data.
#. Once `<bus_name>_ack` has been set to 1, it **shall** remain at 1 until the transaction completes.
#. Whenever `<bus_name>_stb` is 1 and `<bus_name>_ack` are 1, a bus transaction **shall** complete on the following 0 to 1 transition of `clk`.
#. Both the transmitter and receiver **may** commence a new transaction without inserting any wait states.
#. The receiver **may** delay a transaction by inserting wait states until the transmitter indicates that data is available.
#. The transmitter **shall** not delay a transaction by inserting wait states until the receiver is ready to accept data. Deadlock would occur if both the transmitter and receiver delayed a transaction until the other was ready.
::
rst ______________________________________________________________
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _
clk _| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|
_____ _______ ________________________________________________
<bus_name> _____X_VALID_X________________________________________________
_______
<bus_name>_stb _____| |________________________________________________
___
<bus_name>_ack _________| |________________________________________________
^^^^ RX adds wait states
^^^^ Data transfers
rst ______________________________________________________________
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _
clk _| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_|
_____ _______ ________________________________________________
<bus_name> _____X_VALID_X________________________________________________
___
<bus_name>_stb _________| |________________________________________________
_______
<bus_name>_ack _____| |________________________________________________
^^^^ TX adds wait states
^^^^ Data transfers
 
 
rst ______________________________________________________________
__ __ __ __ __ __ __ __ __ __ _
clk _| |__| |__| |__| |__| |__| |__| |__| |__| |__| |_|
_______ ___________ _____ _____ ______________________________
<bus_name> _______X_D0________X_D1__X_D2__X______________________________
_________________
<bus_name>_stb _____________| |______________________________
_______________________
<bus_name>_ack _______| |______________________________
^^^^ TX adds wait states
^^^^ Data transfers
^^^^ stb and ack needn't return to 0 between data words
 
..
/docs/source/tutorial/index.rst
0,0 → 1,138
Tutorial
========
 
Create and Test a C component
-----------------------------
 
Why not start with a simple example. With your favourite text editor, create a
file count.c and add the following::
void count(){
for(i=1; i<=10; i++){
report(i);
}
}
 
You can convert C components into Verilog components using the C2Verilog
compiler. The *iverilog* option causes the generated Verilog component to be
compiled using Icarus Verilog. The *run* option causes simulation to be run::
 
~$ c2verilog iverilog run test.c
1
2
3
4
5
6
7
8
9
10
 
When a design is reset, execution starts with the last function defined in
the C file. This need not be called *main*. The name of the last function
will be used as the name for the generated Verilog component. The C program will
appear to execute in sequence, although the compiler may execute instructions
concurrently if it does not affect the outcome of the program. This will allow
your component to take advantage of the inherent parallelism present in a hardware
design.
 
The *report* function is a *built-in* function which is helpful for debug, it
will print the value of a variable on the console during simulations, when you
synthesise the design it will be ignored.
 
This component doesn't have any inputs or outputs, so it isn't going to be very
useful in a real design. You can add inputs and outputs to a components using
function calls with special names. Functions that start with the name *input_*
or *output_* are interpreted as inputs, or outputs respectively.
 
::
 
int temp;
temp = input_spam(); //reads from an input called spam
temp = input_eggs(); //reads from an input called eggs
output_fish(temp); //writes to an output called fish
 
 
Reading or writing from inputs and outputs causes program execution to block
until data is available. This synchronises data transfers with other components
executing in the same device, this method of passing data between concurrent
processes is much simpler than the mutex/lock/semaphore mechanisms used in
multithreaded applications.
 
If you don't want to commit yourself to reading and input and blocking
execution, you can check if data is ready::
 
int temp;
if(ready_spam()){
temp = input_spam();
}
 
There is no equivalent function to check if an output is ready to receive data,
this could cause deadlocks if both the sending and receiving end were waiting
for one another.
 
We can now construct some basic hardware components quite simply. Here's a counter for instance::
 
void counter(){
while(1){
for(i=1; i<=10; i++){
output_out(i);
}
}
}
 
We can generate an adder like this::
 
void added(){
while(1){
output_z(input_a()+input_b());
}
}
 
Or a divider like this (yes, you can synthesise division)::
 
void divider(){
while(1){
output_z(input_a()/input_b());
}
}
 
We can split a stream of data into two identical data streams using a tee function::
 
void tee(){
int temp;
while(1){
temp = input_a();
output_y(temp);
output_z(temp);
}
}
 
If we want to merge two streams of data, we could interlace them::
 
void interlace(){
int temp;
while(1){
temp = input_a();
output_z(temp);
temp = input_b();
output_z(temp);
}
}
 
or we could prioritise one stream over the other::
 
void arbiter(){
int temp;
while(1){
if( ready_a() ){
temp = input_a();
output_z(temp);
} else if( ready_b() ){
temp = input_b();
output_z(temp);
}
}
}
 
/docs/source/chips.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
docs/source/chips.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: docs/source/conf.py =================================================================== --- docs/source/conf.py (nonexistent) +++ docs/source/conf.py (revision 4) @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# +# Chips documentation build configuration file, created by +# sphinx-quickstart on Wed Apr 13 20:50:22 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.pngmath'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Chips' +copyright = u'2011, Jonathan P Dawson' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.1' +# The full version, including alpha/beta/rc tags. +release = '0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = 'chips.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = 'chips.ico' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Chipsdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Chips.tex', u'Chips Documentation', + u'Jonathan P Dawson', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +latex_logo = 'chips.png' + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} Index: docs/source/examples/example_1.rst =================================================================== --- docs/source/examples/example_1.rst (nonexistent) +++ docs/source/examples/example_1.rst (revision 4) @@ -0,0 +1,76 @@ + + +Calculate Square Root using Newton's Method +------------------------------------------- + +In this example, we calculate the sqrt of a number using `Newton's method +`_. +The problem of finding the square root can be expressed as: + +.. math:: + + n = x^2 + +Which can be rearranged as: + +.. math:: + + f(x) = x^2 - n + +Using Newton's method, we can find numerically the approximate point at which +:math:`f(x) = 0`. Repeated applications of the following expression yield +increasingly accurate approximations of the Square root: + +.. math:: + + f(x_k) = x_{k-1} - \frac{{x_{k-1}}^2 - n}{2x_{k-1}} + +Turning this into a practical solution, the following code calculates the square +root of a floating point number. An initial approximation is refined using +Newton's method until further refinements agree to within a small degree. + +.. code-block:: c + + /* sqrt.c */ + /* Jonathan P Dawson */ + /* 2013-12-23 */ + + /* find absolute value of a floating point number*/ + + float fabs(float n){ + if (n < 0.0) { + return - n; + } else { + return n; + } + } + + /* approximate sqrt using newton's method*/ + + float sqrt(float n){ + float square, x, old; + x = 10.0; + old = 0.0; + while(fabs(old - x) > 0.000001){ + old = x; + x -= (x*x-n)/(2*x); + } + return x; + } + + /* test sqrt function*/ + + void main(){ + float x; + for(x=0.0; x <= 10.0; x+= 0.1){ + file_write(x, "x"); + file_write(sqrt(x), "sqrt_x"); + } + } + +Note that the code isn't entirely robust, and cannot handle special cases such +as Nans, infinities or negative numbers. A simple test calculates +:math:`\sqrt{x}` where :math:`-10 < x < 10`. + +.. image:: images/example_1.png + Index: docs/source/examples/example_2.rst =================================================================== --- docs/source/examples/example_2.rst (nonexistent) +++ docs/source/examples/example_2.rst (revision 4) @@ -0,0 +1,87 @@ + + +Approximating Sine and Cosine functions using Taylor Series +----------------------------------------------------------- + +In this example, we calculate an approximation of the cosine functions using +the `Taylor series `_: + +.. math:: + + \cos (x) = \sum_{n=0}^{\infty} \frac{(-1)^n}{(2n)!} x^{2n} + + +The following example uses the Taylor Series approximation to generate the Sine +and Cosine functions. Successive terms of the taylor series are calculated +until successive approximations agree to within a small degree. A Sine +function is also synthesised using the identity :math:`sin(x) \equiv cos(x-\pi/2)` + +.. code-block:: c + + /* taylor.c */ + /* Jonathan P Dawson */ + /* 2013-12-23 */ + + /* globals */ + float pi=3.14159265359; + + /* approximate the cosine function using Taylor series */ + + float taylor(float angle){ + + float old, approximation, sign, power, fact; + unsigned count, i; + + approximation = 1.0; + old = 0.0; + sign = -1.0; + count = 1; + power = 1.0; + fact = 1.0; + + for(i=2; approximation!=old; i+=2){ + old = approximation; + + while(count<=i){ + power*=angle; + fact*=count; + count++; + } + + approximation += sign*(power/fact); + sign = -sign; + + } + return approximation; + } + + /* return the cosine of angle in radians */ + + float cos(float angle){ + return taylor(angle); + } + + /* return the sine of angle in radians */ + + float sin(float angle){ + return cos(angle-(pi/2)); + } + + + /* test routine */ + + void main(){ + float x; + float step=pi/25; + + for(x=-2*pi; x <= 2*pi; x += step){ + file_write(x, "x"); + file_write(cos(x), "cos_x"); + file_write(sin(x), "sin_x"); + } + } + +A simple test calculates Sine and Cosine for the range :math:`-2\pi <= x <= 2\pi`. + +.. image:: images/example_2.png + Index: docs/source/examples/example_3.rst =================================================================== --- docs/source/examples/example_3.rst (nonexistent) +++ docs/source/examples/example_3.rst (revision 4) @@ -0,0 +1,174 @@ + + +Implement Quicksort +------------------- + +This example sorts an array of data using the +`Quick Sort algorithm `_ + +The quick-sort algorithm is a recurrsive algorithm, but *Chips* does not +support recursive functions. Since the level of recursion is bounded, it is +possible to implement the function using an explicitly created stack. + +.. code-block:: c + + /* fft.c */ + /* Jonathan P Dawson */ + /* 2013-12-23 */ + + /* Based on the in-place algorithm on the Wikipedia page */ + /* http://en.wikipedia.org/wiki/Quicksort#In-place_version */ + + /*globals*/ + const unsigned length = 32; + + /* partition subarray */ + unsigned partition( + int array[], + unsigned left, + unsigned right, + unsigned pivot_index) + { + + int temp, pivot_value; + unsigned i, store_index; + + store_index = left; + pivot_value = array[pivot_index]; + + temp = array[pivot_index]; + array[pivot_index] = array[right]; + array[right] = temp; + + for(i=left; i> 1; + pivot = partition(array, left, right, pivot); + + /* push both subarrays onto stack */ + lefts[stack_pointer] = left; + rights[stack_pointer] = pivot - 1; + stack_pointer++; + lefts[stack_pointer] = pivot + 1; + rights[stack_pointer] = right; + stack_pointer++; + } + + } + + } + + + void main(){ + int array[length]; + unsigned i; + + /* Fill array with zeros */ + for(i=0; i
docs/source/examples/images/example_2.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: docs/source/examples/images/example_3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: docs/source/examples/images/example_3.png =================================================================== --- docs/source/examples/images/example_3.png (nonexistent) +++ docs/source/examples/images/example_3.png (revision 4)
docs/source/examples/images/example_3.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: docs/source/examples/images/example_4.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: docs/source/examples/images/example_4.png =================================================================== --- docs/source/examples/images/example_4.png (nonexistent) +++ docs/source/examples/images/example_4.png (revision 4)
docs/source/examples/images/example_4.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: docs/source/examples/images/example_5.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: docs/source/examples/images/example_5.png =================================================================== --- docs/source/examples/images/example_5.png (nonexistent) +++ docs/source/examples/images/example_5.png (revision 4)
docs/source/examples/images/example_5.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: docs/source/examples/images/example_1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: docs/source/examples/images/example_1.png =================================================================== --- docs/source/examples/images/example_1.png (nonexistent) +++ docs/source/examples/images/example_1.png (revision 4)
docs/source/examples/images/example_1.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: docs/source/examples/example_4.rst =================================================================== --- docs/source/examples/example_4.rst (nonexistent) +++ docs/source/examples/example_4.rst (revision 4) @@ -0,0 +1,35 @@ + + +Pseudo Random Number Generator +------------------------------ + +This example uses a +`Linear Congruential Generator (LCG) `_ to generate Pseudo Random Numbers. + +.. code-block:: c + + /*globals*/ + unsigned long int seed; + + void srand(unsigned long int s){ + seed = s; + } + + unsigned long rand(){ + const unsigned long a = 1103515245ul; + const unsigned long c = 12345ul; + seed = (a*seed+c); + return seed; + } + + void main(){ + unsigned i; + for (i=0; i<4096; i++){ + file_write(rand(), "x"); + file_write(rand(), "y"); + file_write(rand(), "z"); + } + } + +.. image:: images/example_4.png + Index: docs/source/examples/example_5.rst =================================================================== --- docs/source/examples/example_5.rst (nonexistent) +++ docs/source/examples/example_5.rst (revision 4) @@ -0,0 +1,148 @@ + + +Fast Fourier Transform +---------------------- + +This example builds on the Taylor series example. We assume that the sin and +cos routines have been placed into a library of math functions math.h, along +with the definitions of :math:`\pi`, M_PI. + +The `Fast Fourier Transform (FFT) `_ +is an efficient method of decomposing discretely sampled signals into a frequency spectrum, it +is one of the most important algorithms in Digital Signal Processing (DSP). +`The Scientist and Engineer's Guide to Digital Signal Processing `_ +gives a straight forward introduction, and can be viewed on-line for free. + +The example shows a practical method of calculating the FFT using the +`Cooley-Tukey algorithm `_. + + +.. code-block:: c + + /* fft.c */ + /* Jonathan P Dawson */ + /* 2013-12-23 */ + + #include "math.h" + + /*globals*/ + const int n = 1024; + const int m = 10; + float twiddle_step_real[m]; + float twiddle_step_imaginary[m]; + + + /*calculate twiddle factors and store them*/ + void calculate_twiddles(){ + unsigned stage, subdft_size, span; + for(stage=1; stage<=m; stage++){ + subdft_size = 1 << stage; + span = subdft_size >> 1; + twiddle_step_real[stage] = cos(M_PI/span); + twiddle_step_imaginary[stage] = -sin(M_PI/span); + } + } + + /*bit reverse*/ + unsigned bit_reverse(unsigned forward){ + unsigned reversed=0; + unsigned i; + for(i=0; i>= 1; + } + return reversed; + } + + /*calculate fft*/ + void fft(float reals[], float imaginaries[]){ + + int stage, subdft_size, span, i, ip, j; + float sr, si, temp_real, temp_imaginary, imaginary_twiddle, real_twiddle; + + //read data into array + for(i=0; i> 1; + + //initialize trigonometric recurrence + + real_twiddle=1.0; + imaginary_twiddle=0.0; + + sr = twiddle_step_real[stage]; + si = twiddle_step_imaginary[stage]; + + for(j=0; j`_ +homepage. If you want to give it a try in some real hardware, take a look at +the `demo `_ for the Digilent Atlys +Demo card. + +A Quick Taster +============== + +.. code-block:: c + + lfsr.c: + + //4 bit linear feedback shift register + + void lfsr(){ + int new_bit = 0; + int shift_register = 1; + while(1){ + + //tap off bit 2 and 3 + new_bit=((shift_register >> 0) ^ (shift_register >> 1) ^ new_bit); + + //implement shift register + shift_register=((new_bit & 1) << 3) | (shift_register >> 1); + + //4 bit mask + shift_register &= 0xf; + + //write to stream + report(shift_register); + } + } + +:: + + console: + + $ c2verilog iverilog run lfsr.c + + 8 + 12 + 14 + 7 + 3 + 1 + +Documentation +============= +.. toctree:: + :maxdepth: 2 + + language_reference/index + examples/index + tutorial/index + +Links +===== + +- `SciPy`_ Scientific Tools for Python. + +- `matplotlib`_ 2D plotting library for Python. + +- `Python Imaging Library (PIL)`_ Python Imaging Library adds image processing + capabilities to Python. + +- `MyHDL`_ A Hardware description language based on Python. + +.. _`SciPy`: http://scipy.org +.. _`matplotlib`: http://matplotlib.org +.. _`MyHDL`: http://www.myhdl.org +.. _`Python Imaging Library (PIL)`: http://www.pythonware.com/products/pil/ + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + Index: docs/make.bat =================================================================== --- docs/make.bat (nonexistent) +++ docs/make.bat (revision 4) @@ -0,0 +1,113 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +set SPHINXBUILD=sphinx-build +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Chips.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Chips.ghc + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end Index: docs/Makefile =================================================================== --- docs/Makefile (nonexistent) +++ docs/Makefile (revision 4) @@ -0,0 +1,89 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Chips.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Chips.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." Index: c2verilog =================================================================== --- c2verilog (revision 3) +++ c2verilog (revision 4) @@ -7,9 +7,17 @@ import sys import os +import subprocess +import atexit from chips.compiler.compiler import comp +children = [] +def cleanup(): + for child in children: + child.terminate() +atexit.register(cleanup) + if len(sys.argv) < 2 or "help" in sys.argv or "h" in sys.argv: print "Usage: c2verilog.py [options] " print @@ -29,21 +37,24 @@ name, inputs, outputs, documentation = comp(input_file, options) + #run the compiled design using the simulator of your choice. if "iverilog" in sys.argv: - import os - import tempfile - import shutil verilog_file = os.path.abspath("%s.v"%name) - #tempdir = tempfile.mkdtemp() - #os.chdir(tempdir) - os.system("iverilog -o %s %s"%(name, verilog_file)) + process = subprocess.Popen(["iverilog", "-o", str(name), str(verilog_file)]) + children.append(process) + result = process.wait() + children.remove(process) + + if result: + print "Verilog output failed to compile correctly" + sys.exit(result) + if "run" in sys.argv: - result = os.system("vvp %s"%name) - if result: - sys.exit(1) - else: - sys.exit(0) - #shutil.rmtree(tempdir) + process = subprocess.Popen(["vvp", str(name)]) + children.append(process) + result = process.wait() + children.remove(process) + sys.exit(result) #Add more tools here ...
/examples/math.h
0,0 → 1,124
/* This is a very incomplete version of libc math.h
* Not all the funtions and Macros are implemented.
* It has not been tested.
* Special cases have not been catered for*/
 
 
/* globals */
const float M_PI=3.14159265359;
 
/*Taylor series approximation of Cosine function*/
 
float taylor(float angle){
 
float old, approximation, sign, power, fact;
unsigned count, i;
 
approximation = 1.0;
old = 0.0;
sign = -1.0;
count = 1;
power = 1.0;
fact = 1.0;
 
for(i=2; approximation!=old; i+=2){
old = approximation;
 
while(count<=i){
power*=angle;
fact*=count;
count++;
}
 
approximation += sign*(power/fact);
sign = -sign;
 
}
return approximation;
}
 
/*return cos of angle in radians*/
 
float cos(float angle){
return taylor(angle);
}
 
/*return sin of angle in radians*/
 
float sin(float angle){
return cos(angle-(M_PI/2));
}
 
/*return tan of angle in radians*/
 
float tan(float n){
return sin(n) / cos(n);
}
 
/* Return absolute value of a float n*/
 
float fabs(float n){
if (n < 0.0) {
return - n;
} else {
return n;
}
}
 
/* Return absolute value of integer n*/
 
int abs(int n){
if (n < 0) {
return - n;
} else {
return n;
}
}
 
/* return e ** x */
 
float exp(float x){
 
float result = 1.0;
unsigned n = 1;
float power = 1.0;
float factorial = 1.0;
float old = 0.0;
 
while(fabs(old - result) > 0.000001){
old = result;
power *= x;
factorial *= n;
result += (power/factorial);
n++;
}
 
return result;
 
}
 
/* return log_e(n) */
 
float log(float n){
float antilog, x, old;
x = 10.0;
old = 0.0;
while(fabs(old - x) > 0.000001){
old = x;
antilog = exp(x);
x -= (antilog - n)/antilog;
}
return x;
}
 
/* return log_10(n) */
 
float log10(float n){
return log(n)/log(10);
}
 
/* return log_2(n) */
 
float log2(float n){
return log(n)/log(2);
}
/examples/fft.c
0,0 → 1,122
/* fft.c */
/* Jonathan P Dawson */
/* 2013-12-23 */
 
#include "math.h"
 
/*globals*/
const int n = 1024;
const int m = 10;
float twiddle_step_real[m];
float twiddle_step_imaginary[m];
 
 
/*calculate twiddle factors and store them*/
void calculate_twiddles(){
unsigned stage, subdft_size, span;
for(stage=1; stage<=m; stage++){
subdft_size = 1 << stage;
span = subdft_size >> 1;
twiddle_step_real[stage] = cos(M_PI/span);
twiddle_step_imaginary[stage] = -sin(M_PI/span);
}
}
 
/*bit reverse*/
unsigned bit_reverse(unsigned forward){
unsigned reversed=0;
unsigned i;
for(i=0; i<m; i++){
reversed <<= 1;
reversed |= forward & 1;
forward >>= 1;
}
return reversed;
}
 
/*calculate fft*/
void fft(float reals[], float imaginaries[]){
 
int stage, subdft_size, span, i, ip, j;
float sr, si, temp_real, temp_imaginary, imaginary_twiddle, real_twiddle;
 
//read data into array
for(i=0; i<n; i++){
ip = bit_reverse(i);
if(i < ip){
temp_real = reals[i];
temp_imaginary = imaginaries[i];
reals[i] = reals[ip];
imaginaries[i] = imaginaries[ip];
reals[ip] = temp_real;
imaginaries[ip] = temp_imaginary;
}
}
 
//butterfly multiplies
for(stage=1; stage<=m; stage++){
report(stage);
subdft_size = 1 << stage;
span = subdft_size >> 1;
 
//initialize trigonometric recurrence
 
real_twiddle=1.0;
imaginary_twiddle=0.0;
 
sr = twiddle_step_real[stage];
si = twiddle_step_imaginary[stage];
 
for(j=0; j<span; j++){
for(i=j; i<n; i+=subdft_size){
ip=i+span;
 
temp_real = reals[ip]*real_twiddle - imaginaries[ip]*imaginary_twiddle;
temp_imaginary = reals[ip]*imaginary_twiddle + imaginaries[ip]*real_twiddle;
 
reals[ip] = reals[i]-temp_real;
imaginaries[ip] = imaginaries[i]-temp_imaginary;
 
reals[i] = reals[i]+temp_real;
imaginaries[i] = imaginaries[i]+temp_imaginary;
}
//trigonometric recreal_twiddlerence
temp_real=real_twiddle;
real_twiddle = temp_real*sr - imaginary_twiddle*si;
imaginary_twiddle = temp_real*si + imaginary_twiddle*sr;
}
}
}
 
void main(){
float reals[n];
float imaginaries[n];
unsigned i;
 
/* pre-calculate sine and cosine*/
calculate_twiddles();
 
/* generate a 64 sample cos wave */
for(i=0; i<n; i++){
reals[i] = 0.0;
imaginaries[i] = 0.0;
}
for(i=0; i<=64; i++){
reals[i] = sin(2.0 * M_PI * (i/64.0));
}
 
/* output time domain signal to a file */
for(i=0; i<n; i++){
file_write(reals[i], "x_re");
file_write(imaginaries[i], "x_im");
}
 
/* transform into frequency domain */
fft(reals, imaginaries);
 
/* output frequency domain signal to a file */
for(i=0; i<n; i++){
file_write(reals[i], "fft_x_re");
file_write(imaginaries[i], "fft_x_im");
}
}
/examples/example_1.py
0,0 → 1,89
#!/usr/bin/env python
 
import subprocess
import atexit
from math import pi
 
try:
from matplotlib import pyplot
except ImportError:
print "You need matplotlib to run this script!"
exit(0)
 
children = []
def cleanup():
for child in children:
print "Terminating child process"
child.terminate()
atexit.register(cleanup)
 
def run_c(file_name):
process = subprocess.Popen(["../c2verilog", "iverilog", "run", str(file_name)])
children.append(process)
process.wait()
children.remove(process)
 
def test():
run_c("sqrt.c")
x = [float(i) for i in open("x")]
sqrt_x = [float(i) for i in open("sqrt_x")]
pyplot.plot(x, sqrt_x)
pyplot.xlim(0, 10.1)
pyplot.title("Square Root of x")
pyplot.xlabel("x")
pyplot.ylabel("$\\sqrt{x}$")
pyplot.savefig("../docs/source/examples/images/example_1.png")
pyplot.show()
 
def indent(lines):
return "\n ".join(lines.splitlines())
 
def generate_docs():
 
documentation = """
 
Calculate Square Root using Newton's Method
-------------------------------------------
 
In this example, we calculate the sqrt of a number using `Newton's method
<http://en.wikipedia.org/wiki/Newton's_method#Square_root_of_a_number>`_.
The problem of finding the square root can be expressed as:
 
.. math::
 
n = x^2
 
Which can be rearranged as:
 
.. math::
 
f(x) = x^2 - n
 
Using Newton's method, we can find numerically the approximate point at which
:math:`f(x) = 0`. Repeated applications of the following expression yield
increasingly accurate approximations of the Square root:
 
.. math::
 
f(x_k) = x_{k-1} - \\frac{{x_{k-1}}^2 - n}{2x_{k-1}}
 
Turning this into a practical solution, the following code calculates the square
root of a floating point number. An initial approximation is refined using
Newton's method until further refinements agree to within a small degree.
 
.. code-block:: c
 
%s
 
Note that the code isn't entirely robust, and cannot handle special cases such
as Nans, infinities or negative numbers. A simple test calculates
:math:`\\sqrt{x}` where :math:`-10 < x < 10`.
 
.. image:: images/example_1.png
 
"""%indent(open("sqrt.c").read())
 
document = open("../docs/source/examples/example_1.rst", "w").write(documentation)
 
test()
generate_docs()
examples/example_1.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: examples/example_2.py =================================================================== --- examples/example_2.py (nonexistent) +++ examples/example_2.py (revision 4) @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +import subprocess +import atexit +from math import pi + +try: + from matplotlib import pyplot +except ImportError: + print "You need matplotlib to run this script!" + exit(0) + +children = [] +def cleanup(): + for child in children: + print "Terminating child process" + child.terminate() +atexit.register(cleanup) + +def run_c(file_name): + process = subprocess.Popen(["../c2verilog", "iverilog", "run", str(file_name)]) + children.append(process) + process.wait() + children.remove(process) + +def test(): + run_c("taylor.c") + x = [float(i) for i in open("x")] + sin_x = [float(i) for i in open("sin_x")] + cos_x = [float(i) for i in open("cos_x")] + pyplot.xticks( + [-2.0*pi, -pi, 0, pi, 2.0*pi], + [r'$-2\pi$', r"$-\pi$", r'$0$', r'$\pi$', r'$2\pi$']) + pyplot.plot(x, sin_x, label="sin(x)") + pyplot.plot(x, cos_x, label="cos(x)") + pyplot.ylim(-1.1, 1.1) + pyplot.xlim(-2.2 * pi, 2.2 * pi) + pyplot.title("Trig Functions") + pyplot.xlabel("x (radians)") + pyplot.legend(loc="upper left") + pyplot.savefig("../docs/source/examples/images/example_2.png") + pyplot.show() + +def indent(lines): + return "\n ".join(lines.splitlines()) + +def generate_docs(): + + documentation = """ + +Approximating Sine and Cosine functions using Taylor Series +----------------------------------------------------------- + +In this example, we calculate an approximation of the cosine functions using +the `Taylor series `_: + +.. math:: + + \\cos (x) = \\sum_{n=0}^{\\infty} \\frac{(-1)^n}{(2n)!} x^{2n} + + +The following example uses the Taylor Series approximation to generate the Sine +and Cosine functions. Successive terms of the taylor series are calculated +until successive approximations agree to within a small degree. A Sine +function is also synthesised using the identity :math:`sin(x) \\equiv cos(x-\\pi/2)` + +.. code-block:: c + + %s + +A simple test calculates Sine and Cosine for the range :math:`-2\\pi <= x <= 2\\pi`. + +.. image:: images/example_2.png + +"""%indent(open("taylor.c").read()) + + document = open("../docs/source/examples/example_2.rst", "w").write(documentation) + +test() +generate_docs()
examples/example_2.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: examples/example_3.py =================================================================== --- examples/example_3.py (nonexistent) +++ examples/example_3.py (revision 4) @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +import subprocess +import atexit +from math import pi + +children = [] +def cleanup(): + for child in children: + print "Terminating child process" + child.terminate() +atexit.register(cleanup) + +def run_c(file_name): + process = subprocess.Popen(["../c2verilog", "iverilog", "run", str(file_name)]) + children.append(process) + process.wait() + children.remove(process) + +def test(): + run_c("sort.c") + +def indent(lines): + return "\n ".join(lines.splitlines()) + +def generate_docs(): + + documentation = """ + +Implement Quicksort +------------------- + +This example sorts an array of data using the +`Quick Sort algorithm `_ + +The quick-sort algorithm is a recurrsive algorithm, but *Chips* does not +support recursive functions. Since the level of recursion is bounded, it is +possible to implement the function using an explicitly created stack. + +.. code-block:: c + + %s + +The algorithm is tested using an array containing out of order values. The program correctly sorts the array:: + + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 0 (report at line: 122 in file: sort.c) + 1 (report at line: 122 in file: sort.c) + 2 (report at line: 122 in file: sort.c) + 3 (report at line: 122 in file: sort.c) + 4 (report at line: 122 in file: sort.c) + 5 (report at line: 122 in file: sort.c) + 6 (report at line: 122 in file: sort.c) + 7 (report at line: 122 in file: sort.c) + 8 (report at line: 122 in file: sort.c) + 9 (report at line: 122 in file: sort.c) + 10 (report at line: 122 in file: sort.c) + 11 (report at line: 122 in file: sort.c) + 12 (report at line: 122 in file: sort.c) + 13 (report at line: 122 in file: sort.c) + 14 (report at line: 122 in file: sort.c) + 15 (report at line: 122 in file: sort.c) + 16 (report at line: 122 in file: sort.c) + +"""%indent(open("sort.c").read()) + + document = open("../docs/source/examples/example_3.rst", "w").write(documentation) + +test() +generate_docs()
examples/example_3.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: examples/rand.c =================================================================== --- examples/rand.c (nonexistent) +++ examples/rand.c (revision 4) @@ -0,0 +1,22 @@ +/*globals*/ +unsigned long int seed; + +void srand(unsigned long int s){ + seed = s; +} + +unsigned long rand(){ + const unsigned long a = 1103515245ul; + const unsigned long c = 12345ul; + seed = (a*seed+c); + return seed; +} + +void main(){ + unsigned i; + for (i=0; i<4096; i++){ + file_write(rand(), "x"); + file_write(rand(), "y"); + file_write(rand(), "z"); + } +} Index: examples/.gitignore =================================================================== --- examples/.gitignore (nonexistent) +++ examples/.gitignore (revision 4) @@ -0,0 +1,14 @@ +x +y +z +sin_x +cos_x +main +main.v +fft_x_im +fft_x_re +x_im +x_re +e_x +log_x +sqrt_x Index: examples/example_4.py =================================================================== --- examples/example_4.py (nonexistent) +++ examples/example_4.py (revision 4) @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import subprocess +import atexit +from math import pi + +try: + from matplotlib import pyplot + from mpl_toolkits.mplot3d import Axes3D +except ImportError: + print "You need matplotlib to run this script!" + exit(0) + +children = [] +def cleanup(): + for child in children: + print "Terminating child process" + child.terminate() +atexit.register(cleanup) + +def run_c(file_name): + process = subprocess.Popen(["../c2verilog", "iverilog", "run", str(file_name)]) + children.append(process) + process.wait() + children.remove(process) + +def test(): + run_c("rand.c") + x = [float(i) for i in open("x")] + y = [float(i) for i in open("y")] + z = [float(i) for i in open("z")] + + fig = pyplot.figure() + ax = fig.add_subplot(111, projection="3d") + ax.scatter(x, y, z, c='b', marker='^') + pyplot.title("Random Plot") + pyplot.savefig("../docs/source/examples/images/example_4.png") + pyplot.show() + +def indent(lines): + return "\n ".join(lines.splitlines()) + +def generate_docs(): + + documentation = """ + +Pseudo Random Number Generator +------------------------------ + +This example uses a +`Linear Congruential Generator (LCG) `_ to generate Pseudo Random Numbers. + +.. code-block:: c + + %s + +.. image:: images/example_4.png + +"""%indent(open("rand.c").read()) + + document = open("../docs/source/examples/example_4.rst", "w").write(documentation) + +test() +generate_docs()
examples/example_4.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: examples/example_5.py =================================================================== --- examples/example_5.py (nonexistent) +++ examples/example_5.py (revision 4) @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +import subprocess +import atexit +from math import pi + +try: + import scipy as s +except ImportError: + print "You need scipy to run this script!" + exit(0) + +try: + import numpy as n +except ImportError: + print "You need numpy to run this script!" + exit(0) + +try: + from matplotlib import pyplot +except ImportError: + print "You need matplotlib to run this script!" + exit(0) + +children = [] +def cleanup(): + for child in children: + print "Terminating child process" + child.terminate() +atexit.register(cleanup) + +def run_c(file_name): + process = subprocess.Popen(["../c2verilog", "iverilog", "run", str(file_name)]) + children.append(process) + process.wait() + children.remove(process) + +def test(): + run_c("fft.c") + x_re = [float(i) for i in open("x_re")] + x_im = [float(i) for i in open("x_im")] + fft_x_re = [float(i) for i in open("fft_x_re")] + fft_x_im = [float(i) for i in open("fft_x_im")] + + time_complex = [i + (j*1.0) for i, j in zip(x_re, x_im)] + numpy_complex = s.fft(time_complex) + numpy_magnitude = n.abs(numpy_complex) + + chips_complex = [i + (j*1.0j) for i, j in zip(fft_x_re, fft_x_im)] + chips_magnitude = n.abs(chips_complex) + + f, subplot = pyplot.subplots(3, sharex=True) + + pyplot.subplots_adjust(hspace=1.0) + subplot[0].plot(x_re, 'g') + subplot[1].plot(numpy_magnitude, 'r') + subplot[2].plot(chips_magnitude, 'b') + pyplot.xlim(0, 1023) + subplot[0].set_title("Time Domain Signal (64 point sine)") + subplot[1].set_title("Frequency Spectrum - Numpy") + subplot[2].set_title("Frequency Spectrum - Chips") + subplot[0].set_xlabel("Sample") + subplot[1].set_xlabel("Sample") + subplot[2].set_xlabel("Sample") + pyplot.savefig("../docs/source/examples/images/example_5.png") + pyplot.show() + +def indent(lines): + return "\n ".join(lines.splitlines()) + +def generate_docs(): + + documentation = """ + +Fast Fourier Transform +---------------------- + +This example builds on the Taylor series example. We assume that the sin and +cos routines have been placed into a library of math functions math.h, along +with the definitions of :math:`\\pi`, M_PI. + +The `Fast Fourier Transform (FFT) `_ +is an efficient method of decomposing discretely sampled signals into a frequency spectrum, it +is one of the most important algorithms in Digital Signal Processing (DSP). +`The Scientist and Engineer's Guide to Digital Signal Processing `_ +gives a straight forward introduction, and can be viewed on-line for free. + +The example shows a practical method of calculating the FFT using the +`Cooley-Tukey algorithm `_. + + +.. code-block:: c + + %s + +The C code includes a simple test routine that calculates the frequency spectrum of a 64 point sine wave. + +.. image:: images/example_5.png + +"""%indent(open("fft.c").read()) + + document = open("../docs/source/examples/example_5.rst", "w").write(documentation) + +test() +generate_docs()
examples/example_5.py Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: examples/stdlib.h =================================================================== --- examples/stdlib.h (nonexistent) +++ examples/stdlib.h (revision 4) @@ -0,0 +1,14 @@ +const unsigned long RAND_MAX = 0xfffffffful; + +unsigned long int seed; + +void srand(unsigned long int s){ + seed = s; +} + +unsigned long rand(){ + const unsigned long a = 1103515245ul; + const unsigned long c = 12345ul; + seed = (a*seed+c); + return seed; +} Index: examples/sort.c =================================================================== --- examples/sort.c (nonexistent) +++ examples/sort.c (revision 4) @@ -0,0 +1,124 @@ +/* fft.c */ +/* Jonathan P Dawson */ +/* 2013-12-23 */ + +/* Based on the in-place algorithm on the Wikipedia page */ +/* http://en.wikipedia.org/wiki/Quicksort#In-place_version */ + +/*globals*/ +const unsigned length = 32; + +/* partition subarray */ +unsigned partition( + int array[], + unsigned left, + unsigned right, + unsigned pivot_index) +{ + + int temp, pivot_value; + unsigned i, store_index; + + store_index = left; + pivot_value = array[pivot_index]; + + temp = array[pivot_index]; + array[pivot_index] = array[right]; + array[right] = temp; + + for(i=left; i> 1; + pivot = partition(array, left, right, pivot); + + /* push both subarrays onto stack */ + lefts[stack_pointer] = left; + rights[stack_pointer] = pivot - 1; + stack_pointer++; + lefts[stack_pointer] = pivot + 1; + rights[stack_pointer] = right; + stack_pointer++; + } + + } + +} + + +void main(){ + int array[length]; + unsigned i; + + /* Fill array with zeros */ + for(i=0; i 0.000001){ + old = x; + x -= (x*x-n)/(2*x); + } + return x; +} + +/* test sqrt function*/ + +void main(){ + float x; + for(x=0.0; x <= 10.0; x+= 0.1){ + file_write(x, "x"); + file_write(sqrt(x), "sqrt_x"); + } +} Index: examples/taylor.c =================================================================== --- examples/taylor.c (nonexistent) +++ examples/taylor.c (revision 4) @@ -0,0 +1,62 @@ +/* taylor.c */ +/* Jonathan P Dawson */ +/* 2013-12-23 */ + +/* globals */ +float pi=3.14159265359; + +/* approximate the cosine function using Taylor series */ + +float taylor(float angle){ + + float old, approximation, sign, power, fact; + unsigned count, i; + + approximation = 1.0; + old = 0.0; + sign = -1.0; + count = 1; + power = 1.0; + fact = 1.0; + + for(i=2; approximation!=old; i+=2){ + old = approximation; + + while(count<=i){ + power*=angle; + fact*=count; + count++; + } + + approximation += sign*(power/fact); + sign = -sign; + + } + return approximation; +} + +/* return the cosine of angle in radians */ + +float cos(float angle){ + return taylor(angle); +} + +/* return the sine of angle in radians */ + +float sin(float angle){ + return cos(angle-(pi/2)); +} + + +/* test routine */ + +void main(){ + float x; + float step=pi/25; + + for(x=-2*pi; x <= 2*pi; x += step){ + file_write(x, "x"); + file_write(cos(x), "cos_x"); + file_write(sin(x), "sin_x"); + } +} Index: . =================================================================== --- . (revision 3) +++ . (revision 4)
. Property changes : Added: ignore ## -0,0 +1 ## +build Added: isvn:ignore ## -0,0 +1,2 ## +*.bak +build

powered by: WebSVN 2.1.0

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