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 (KKKKKKKKKKKKKKKKKKKK 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«KK±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 KKK
-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 KK
-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¬KK®K¯K°K±K³eUF/media/sdb1/Projects/SP605_DEMO/chips2/chips/compiler/verilog_speed.pyq]q(KKKKKKKKKKKKKKKK)K.K/K0K1K2K3K5K6K7K:K;K