#####################################
# File: pyHardwareCore.py
# Author: Norbert Feurle
# start Date: 2.2.2012
# latest Edit: 23.2.2012
#
# Description: Python Hardware Processor
# This Code implements a Hardware CPU in myhdl. The code for the CPU is drictly written in python
# and since the hardware description is also in python, the programmcode is automatically loaded into the design
# The cool thing is that with this approach only memory and stack hardware is allocated in Hardware which is
# really needed. The Simulation of the cpu code on the hardware can be done in python only (only python needed! and of corse myhdl).
# The bytecode of python is executed in the CPU with one instruction per cycle
# You can simply instantiate more cores on an FPGA with different Programmcode to make them run in parallel
#
# License: Pro life licence.
# You are not allowed to use this code for any purpose which is in any kind disrespectfully to life and/or freedom
# In such a case it remains my property
# for example: You are not allowed to build weapons, or large-scale animal husbandry automation equipment or anything
# that is used to harm, destroy or is used to frighten living beeings at an unacceptable rate, or build hardware
# with it where the workers dont get paid appropriate, or any process where the waste issue isnt solved in a sustainable way,
# etc..
# If you use it respectfully you are allowed to use it for free and are welcome to contribute with your changes/extensions
# You also have to keep this licence.
#################################################################################################
########################################################################################
#### Limitations:
#### no lists, no dicts no tuples, no float, no complex numbers, etc.
#### no classmembers,no multiplication, no exeptions, no for x in xxx:, etc.
########################################################################################
### What is supported:
#---------------------------------------------------
### ints (with x bits), no other python types only plane ints
### if and while (comparisions with <,>, >=, <=,!=,== )
### nested while loops up to CONST_LOOP_DEPTH (Constant Default value = 4)
### assignments to globals or local varibles from const, globals or define local variables
### Operators: +. -, ^ ,~, |, & ,<<,>>
### Simple Digital IOs over PORTS
### Function calls (with consts,and globals, or vars as argument, one intager as return value), no default arguments, no keyword arguments,no other functions as arguments
### up to MAX_NUMBER_FUNCTION_ARGUMENTS (Constant Default value = 10) arguments
### up to CONST_PC_STACK_DEPTH (Constant Default value=5) number of nested function calls
### up to VAR_MEM_DEPTH (Constant Default value=20) local variables
########################################################################################
###################################################################
##### Bug Track / Upcomming Features list :
#---------------------------------------------
# (done) Binary operations remove doesnt removes the operands from stack
# (done but stack ram could be smaller) (but stack_mem is now very big, Solution -> add some cycles for rot_two, rot_three and rot_for and put stak into a RAM,maybe dualported ) dis.opmap['POP_BLOCK'] and dis.opmap['SETUP_LOOP'] clear stack
# (halve done) Global memory initilisation in myhdl
# (done)-> GLOBAL_CONTENT is set to (0,) in this case <- if there is no function exept CPU_main, toVHDL creates an error,probably because Global_mem is empty
# (done) hasattr(eval(currentfunction.func_code.co_names[actual_Argument]), '__call__') througs exeption if PORTA_IN, etc is note defined global (defining PREDEFINED_IO_ADDRESSES should be enough)
# (mostly done ) wheater make PORTS in a all positive range or all with -2**(x-1) to +2**(x-1) conversion from signed to unsigned
# (done) Functions need to be able to use vars from var_mem as arguments (Dual ported var_mem)
# TODO calling a function with an function as an argument would not work
# TODO ROT_FOUR is not yet supported, adding a extra cycles is needed
# TODO Test generated VHDL code, and on an FPGA, maybe cosimulation
# TODO More Programm tests, Clean UP code, for example: eliminate magic numbers,general cleanup
# (done) insert cycle after var_mem is read to make it possible to map it into ram, same for programm_code
# TODO make jumps to addresses possible which exeed the size of VAR_BITWIDTH, for example to make a usable processor with WORD_SZ=4 bit
# TODO generic addable multiplication support
########info:
# ROT_TWO after SETUP_LOOP would not work but is kind of usless because the new stack block is empty
##########################################
#################################################################
####### Nice to haves:
#-----------------------------
# TODO maybe support List of ints with single integer subscription
# TODO additional SPI,RS232,I2C,Timer,etc modules
# TODO call functions from extern which are not loaded at startup
# TODO dynamically generate I/O Ports on the processor dependend on PREDEFINED_IO_ADDRESSES
#################################################################
##### The main programm the cpu should execute ####
PREDEFINED_IO_ADDRESSES={'PORTA_IN':0,'PORTB_IN':1,'PORTC_OUT':2,'PORTD_OUT':3, \
'RS232Data':4,'RS232_READ_ADDRESS':5,'RS232_RECEIVE_ADDRESS':6,'RS232_WRITEBUFFER_FULL':7 } #need to start at 0
global_argument=2
def kate(Cycles,argx):
global PORTC_OUT,PORTD_OUT
x=0
PORTD_OUT=PORTD_OUT+argx
while x<Cycles:
x=x+1
PORTC_OUT=PORTC_OUT^8
return 2
def delay(Cycles1,Cycles2):
global PORTC_OUT
x=5
while x<(Cycles1+Cycles2):
x=x+1
PORTC_OUT=PORTC_OUT^4
x=0
while x<kate(1,global_argument):
PORTC_OUT=PORTC_OUT^2
x=x+1
def CPU_main():
global PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,RS232Data # at least output ports need to be defined as gloabals
x=0
a=7
b=8
var_argument_b=3
var_argument_b=var_argument_b+1
#RS232Data=0x4
while 1:
x=x+1
#funcas(kkt(3)) # TODO calling a function with an function as an argument would not work
delay(global_argument,var_argument_b)
if PORTA_IN==1:
PORTC_OUT=PORTC_OUT^1
if x<20:
PORTD_OUT=x
elif 20<=x<25: #x>=20 and x<25: #both work
PORTD_OUT=(2**7)+x
else:
PORTD_OUT=x
a,b=b,a
PORTD_OUT=a<<1
def wait(time):
x=0
while x<100:
td=0
x=x+1
while td<100:
td=td+1
ss=0
while ss<time:
ss=ss+1
def CPU2_main():
global PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT
x=0
while 1:
PORTD_OUT=PORTD_OUT^16
wait(20)
if (PORTB_IN & 0x01)==1:
PORTD_OUT=PORTD_OUT|0x20
else:
PORTD_OUT=PORTD_OUT&0xdf
#PORTD_OUT=PORTD_OUT^16
#PORTD_OUT=PORTD_OUT^16
#if (PORTA_IN & 0x01)==1:
# PORTC_OUT=255
#else:
# PORTC_OUT=0
def CPU_main_RS232_TEST():
global PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,RS232Data,RS232_READ_ADDRESS,RS232_RECEIVE_ADDRESS,RS232_WRITEBUFFER_FULL
x=55
RS232_READ_ADDRESS=0
lastrx_addr=0
while 1:
##### RS232 Transmitting ######
if not RS232_WRITEBUFFER_FULL:
RS232Data=x ### write the value of x to the RS232 Transmitt buffer, this also starts sending the data
x=x+1
PORTC_OUT=PORTC_OUT^1
##### RS232 Receiving ######
if RS232_READ_ADDRESS!=RS232_RECEIVE_ADDRESS:
PORTD_OUT=RS232Data #read data from receive buffer at RS232_READ_ADDRESS
RS232_READ_ADDRESS=RS232_RECEIVE_ADDRESS #(RS232_READ_ADDRESS+1)&0x07 ##### buffer size is 8
#####put the hole rs232 receive buffer to PORTD_OUT when full ####
if lastrx_addr!=RS232_RECEIVE_ADDRESS:
if lastrx_addr==7:
count=0
lastrx_addr=0
while count<=7:
RS232_READ_ADDRESS=count
PORTD_OUT=RS232Data
count=count+1
lastrx_addr=RS232_RECEIVE_ADDRESS
##### End of the main programm ####
import MakeProcessorBytecode
#ProcessorCodeObject=MakeProcessorBytecode.MakeBytecode(CPU_main,PREDEFINED_IO_ADDRESSES,globals())
ProcessorCodeObject=MakeProcessorBytecode.MakeBytecode(CPU_main_RS232_TEST,PREDEFINED_IO_ADDRESSES,globals())
#### Needed for the processor
GLOBAL_FUNCTION_ADRESSES_START=ProcessorCodeObject.GLOBAL_FUNCTION_ADRESSES_START
GLOBALS_MEM_CONTENT=ProcessorCodeObject.GLOBALS_MEM_CONTENT #tuple(GLOBALS_MEM_CONTENT)
CONSTANTS_MEM_CONTENT=ProcessorCodeObject.CONSTANTS_MEM_CONTENT #tuple(CONSTANTS_MEM_CONTENT)
COMPLETE_PROGRAMM_OPCODES=ProcessorCodeObject.COMPLETE_PROGRAMM_OPCODES #tuple(COMPLETE_PROGRAMM_OPCODES)
COMPLETE_PROGRAMM_ARGS=ProcessorCodeObject.COMPLETE_PROGRAMM_ARGS #tuple(COMPLETE_PROGRAMM_ARGS)
GLOBAL_OPCODE_ARG_MAX_VALUE=ProcessorCodeObject.GLOBAL_OPCODE_ARG_MAX_VALUE #max(COMPLETE_PROGRAMM_ARGS)
GLOBAL_STACK_SIZE=ProcessorCodeObject.GLOBAL_STACK_SIZE ### get max stacksize
###### Start of the Processor myhdl implementation ############
import sys
try:
sys.path.remove('/usr/local/lib/python2.7/dist-packages')
except:
pass
sys.path.append('/home/mevets4/Dokumente/myhdl')
from myhdl import *
#import math
def DP_RAM(dout, din, addr_wr,addr_rd, we, clk, WORD_SZ=8, DEPTH=16384):
"""
"""
mem = [Signal(intbv(0,min=-2**(WORD_SZ-1),max=2**(WORD_SZ-1))) for i in range(DEPTH)]
@always(clk.posedge)
def write_read():
if we:
mem[int(addr_wr)].next = din
dout.next = mem[int(addr_rd)]
#@always_comb
#def read():
return write_read
def RAM(clk,dout,addr,CONTENT,WORD_SZ=8):
Converttosigned_sig=Signal(intbv(0,min=dout.min*2,max=dout.max*2))
@always_comb
def combi_log():
Converttosigned_sig.next=CONTENT[int(addr)] #workaround to allow greater than min to max range in positive be written to port
@always(clk.posedge)
def rom_logic():
dout.next= Converttosigned_sig[8:].signed() #CONTENT[int(addr)]
return rom_logic,combi_log
def ProgrammRAM(clk,rst,Opcode,Arg1,addr,OPCODE_CONTENT,OPCODE_ARGUMENTS_CONTENT):
#OPCODE_MEM=PROGRAMM_CONTENT[0]
#ARG_MEM=PROGRAMM_CONTENT[0]
@always(clk.posedge)
def progrom_logic():
#print "address:", addr
Opcode.next= OPCODE_CONTENT[int(addr)]
Arg1.next= OPCODE_ARGUMENTS_CONTENT[int(addr)]
return progrom_logic
GLOBAL_NUMBERSTACK_OPS=22
STACK_NOP,STACK_ADD,STACK_POSITIVE,STACK_NOT,STACK_NEGATIVE,STACK_INVERT,STACK_RSHIFT,STACK_LSHIFT,STACK_AND,STACK_SUB,STACK_OR,STACK_XOR,STACK_POP,STACK_LOAD,STACK_CMP,STACK_ROT_FOUR, STACK_ROT_TWO, STACK_ROT_THREE_0,STACK_ROT_THREE_1,STACK_DUP_TOP,STACK_SETUP_LOOP,STACK_POP_BLOCK=range(GLOBAL_NUMBERSTACK_OPS)
def Stack(clk,rst,TopData_Out,Data_In,StackOP,CMPmode,WORD_SZ=32,SIZE=4):
CONST_LOOP_DEPTH=5 #TODO magic number
if SIZE<4:
SIZE=4
Stack_mem = [Signal(intbv(0,min=-2**(WORD_SZ-1),max=2**(WORD_SZ-1))) for i in range(SIZE*CONST_LOOP_DEPTH)]
stack_read_addr=Signal(intbv(0,min=0,max=SIZE*CONST_LOOP_DEPTH))
stack_write_addr=Signal(intbv(0,min=0,max=SIZE*CONST_LOOP_DEPTH))
TOF_RAM_Data=Signal(intbv(0,min=-2**(WORD_SZ-1),max=2**(WORD_SZ-1)))
Data_to_REG=Signal(intbv(0,min=-2**(WORD_SZ-1),max=2**(WORD_SZ-1)))
#Data_to_REG_RD=Signal(intbv(0,min=-2**(WORD_SZ-1),max=2**(WORD_SZ-1)))
REG_TopOfStack_Data=Signal(intbv(0,min=-2**(WORD_SZ-1),max=2**(WORD_SZ-1)))
TOS_pointer=Signal(intbv(0,min=0,max=SIZE))
TOS_pointer_pre=Signal(intbv(0,min=0,max=SIZE))
#TOS3_pointer= Signal(intbv(0,min=0,max=SIZE))
REG_StackOP=Signal(intbv(0,min=0,max=GLOBAL_NUMBERSTACK_OPS))
REG_CmpMode=Signal(intbv(0,min=0,max=6))
enable_stackpointer_increase=Signal(bool(0))
enable_stackpointer_deacrease=Signal(bool(0))
enable_stack_write_data=Signal(bool(0))
stack_offset=Signal(intbv(0,min=0,max=SIZE*CONST_LOOP_DEPTH))
stack_pos_mem=[Signal(intbv(0,min=0,max=SIZE)) for i in range(CONST_LOOP_DEPTH+1)]
stack_pos_mem_addr=Signal(intbv(0,min=0,max=CONST_LOOP_DEPTH+1))
SaveStack_pos=Signal(bool(0))
ReturnToStack_pos=Signal(bool(0))
#SaveStack_pos_function=Signal(bool(0))
@always(clk.posedge,rst.negedge)
def seq_logic():
if rst == 0:
TOS_pointer.next=0
stack_pos_mem_addr.next=0
stack_offset.next=0
REG_StackOP.next=STACK_NOP
REG_CmpMode.next=0
else:
if enable_stackpointer_increase:
TOS_pointer.next=(TOS_pointer+1)%SIZE
if enable_stackpointer_increase or enable_stack_write_data:
Stack_mem[int(stack_write_addr)].next=Data_to_REG
if enable_stackpointer_deacrease:
TOS_pointer.next=(TOS_pointer-1)%SIZE
if SaveStack_pos:
#print "####### Save stack pos:",TOS_pointer
stack_pos_mem[int(stack_pos_mem_addr)].next=TOS_pointer
stack_pos_mem_addr.next=stack_pos_mem_addr+1
stack_offset.next=stack_offset+SIZE
if ReturnToStack_pos:
#print "####### Return stack pos:",TOS_pointer_pre
TOS_pointer.next=TOS_pointer_pre
stack_pos_mem_addr.next=stack_pos_mem_addr-1
stack_offset.next=stack_offset-SIZE
TOS_pointer_pre.next=(stack_pos_mem[int(stack_pos_mem_addr-1)])
# if StackOP==STACK_LOAD:
# REG_TopOfStack_Data.next=Data_In
#else:
REG_TopOfStack_Data.next=Data_to_REG
REG_StackOP.next=StackOP
REG_CmpMode.next= CMPmode
TOF_RAM_Data.next=Stack_mem[int(stack_read_addr)]
#@always_comb
#def comb_logic2():
#TOS_Data_RD.next#=Stack_mem[int(TOS_pointer+stack_offset)]
#TOS1_Data_RD.next=Stack_mem[int(TOS1_pointer+stack_offset)]
#TOS2_Data_RD.next=Stack_mem[int(TOS2_pointer+stack_offset)]
#TopData_Out.next=Data_to_REG #Stack_mem[int(TOS_pointer+stack_offset)]
@always_comb
def comb_logic():
#Data_to_REG_RD.next=REG_TopOfStack_Data
stack_write_addr.next=TOS_pointer+stack_offset
stack_read_addr.next=((TOS_pointer-1)%SIZE)+stack_offset
#Data_to_stackmem.next=REG_TopOfStack_Data
Data_to_REG.next=REG_TopOfStack_Data
#TOS_Data.next=REG_TopOfStack_Data
TopData_Out.next=REG_TopOfStack_Data
#TopData_Out.next=0
SaveStack_pos.next=False
ReturnToStack_pos.next=False
enable_stackpointer_increase.next=1
enable_stackpointer_deacrease.next=0
enable_stack_write_data.next=0
if REG_StackOP==STACK_LOAD:
Data_to_REG.next=Data_In
TopData_Out.next=Data_In
elif REG_StackOP==STACK_POP:
TopData_Out.next=TOF_RAM_Data
Data_to_REG.next=TOF_RAM_Data
elif REG_StackOP==STACK_ADD:
Data_to_REG.next=TOF_RAM_Data+REG_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data+REG_TopOfStack_Data
elif REG_StackOP==STACK_POSITIVE: #???
Data_to_REG.next=REG_TopOfStack_Data
TopData_Out.next=REG_TopOfStack_Data
#TOS_Data.next=TOS_Data_RD
elif REG_StackOP==STACK_NOT:
Data_to_REG.next=not REG_TopOfStack_Data
TopData_Out.next=not REG_TopOfStack_Data
#TOS_Data.next=TOS_Data_RD
elif REG_StackOP==STACK_NEGATIVE:
Data_to_REG.next=-REG_TopOfStack_Data
TopData_Out.next=-REG_TopOfStack_Data
#TOS_Data.next=-TOS_Data_RD
elif REG_StackOP==STACK_INVERT:
Data_to_REG.next=~REG_TopOfStack_Data
TopData_Out.next=~REG_TopOfStack_Data
#TOS_Data.next=~TOS_Data_RD
elif REG_StackOP==STACK_RSHIFT:
Data_to_REG.next=TOF_RAM_Data>>REG_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data>>REG_TopOfStack_Data
#TOS1_Data.next=TOS1_Data_RD>>TOS_Data_RD
elif REG_StackOP==STACK_LSHIFT:
Data_to_REG.next=TOF_RAM_Data<<REG_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data<<REG_TopOfStack_Data
#TOS1_Data.next=TOS1_Data_RD<<TOS_Data_RD
elif REG_StackOP==STACK_AND:
Data_to_REG.next=TOF_RAM_Data®_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data®_TopOfStack_Data
#TOS1_Data.next=TOS1_Data_RD&TOS_Data_RD
elif REG_StackOP==STACK_SUB:
Data_to_REG.next=TOF_RAM_Data-REG_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data-REG_TopOfStack_Data
#TOS1_Data.next=TOS1_Data_RD-TOS_Data_RD
elif REG_StackOP==STACK_OR:
Data_to_REG.next=TOF_RAM_Data|REG_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data|REG_TopOfStack_Data
elif REG_StackOP==STACK_XOR:
Data_to_REG.next=TOF_RAM_Data^REG_TopOfStack_Data
TopData_Out.next=TOF_RAM_Data^REG_TopOfStack_Data
elif REG_StackOP==STACK_ROT_TWO:
TopData_Out.next=TOF_RAM_Data
Data_to_REG.next=TOF_RAM_Data
elif REG_StackOP==STACK_ROT_THREE_1:
TopData_Out.next=TOF_RAM_Data
Data_to_REG.next=TOF_RAM_Data
#elif REG_StackOP==STACK_DUP_TOP:
# TopData_Out.next=REG_TopOfStack_Data #is standard assignment
# Data_to_REG.next=REG_TopOfStack_Data
elif REG_StackOP==STACK_POP_BLOCK:
TopData_Out.next=TOF_RAM_Data
Data_to_REG.next=TOF_RAM_Data
elif REG_StackOP==STACK_CMP:
if REG_CmpMode==0: #operator <
if TOF_RAM_Data<REG_TopOfStack_Data:
Data_to_REG.next=1
TopData_Out.next=1
else:
Data_to_REG.next=0
TopData_Out.next=0
if REG_CmpMode==1: #operator <=
if TOF_RAM_Data<=REG_TopOfStack_Data:
Data_to_REG.next=1
TopData_Out.next=1
else:
Data_to_REG.next=0
TopData_Out.next=0
if REG_CmpMode==2: #operator ==
if TOF_RAM_Data==REG_TopOfStack_Data:
Data_to_REG.next=1
TopData_Out.next=1
else:
Data_to_REG.next=0
TopData_Out.next=0
if REG_CmpMode==3: #operator !=
if TOF_RAM_Data!=REG_TopOfStack_Data:
Data_to_REG.next=1
TopData_Out.next=1
else:
Data_to_REG.next=0
TopData_Out.next=0
if REG_CmpMode==4: #operator >
if TOF_RAM_Data>REG_TopOfStack_Data:
Data_to_REG.next=1
TopData_Out.next=1
else:
Data_to_REG.next=0
TopData_Out.next=0
if REG_CmpMode==5: #operator >=
if TOF_RAM_Data>=REG_TopOfStack_Data:
Data_to_REG.next=1
TopData_Out.next=1
else:
Data_to_REG.next=0
TopData_Out.next=0
if StackOP==STACK_NOP:
enable_stackpointer_increase.next=0
elif StackOP==STACK_SETUP_LOOP:
enable_stackpointer_increase.next=1
SaveStack_pos.next=True
elif StackOP==STACK_POP_BLOCK:
stack_read_addr.next=((TOS_pointer_pre)%SIZE)+(stack_offset-SIZE)
enable_stackpointer_increase.next=0
ReturnToStack_pos.next=True
elif StackOP==STACK_POSITIVE: #???
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
#TOS_Data.next=TOS_Data_RD
elif StackOP==STACK_NOT:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
#TOS_Data.next=TOS_Data_RD
elif StackOP==STACK_NEGATIVE:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
#TOS_Data.next=-TOS_Data_RD
elif StackOP==STACK_INVERT:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
#TOS_Data.next=~TOS_Data_RD
elif StackOP==STACK_ADD:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD+TOS_Data_RD
elif StackOP==STACK_RSHIFT:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD>>TOS_Data_RD
elif StackOP==STACK_LSHIFT:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD<<TOS_Data_RD
elif StackOP==STACK_AND:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD&TOS_Data_RD
elif StackOP==STACK_SUB:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD-TOS_Data_RD
elif StackOP==STACK_OR:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD|TOS_Data_RD
elif StackOP==STACK_XOR:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
#TOS1_Data.next=TOS1_Data_RD^TOS_Data_RD
elif StackOP==STACK_POP:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=1
# elif StackOP==STACK_CALL_FUNCTION:
# enable_stackpointer_increase.next=0
# enable_stackpointer_deacrease.next=1 #pop function address
# SaveStack_pos_function.next=True
elif StackOP==STACK_LOAD:
enable_stackpointer_increase.next=1
enable_stackpointer_deacrease.next=0
#TopOfStack_Data.next=Data_In
elif StackOP==STACK_ROT_TWO:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
enable_stack_write_data.next=1
stack_write_addr.next=((TOS_pointer-1)%SIZE)+stack_offset
#TOS_Data.next=TOS1_Data_RD
#TOS1_Data.next=TOS_Data_RD
elif StackOP==STACK_ROT_THREE_0:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
enable_stack_write_data.next=1
stack_write_addr.next=((TOS_pointer-2)%SIZE)+stack_offset
stack_read_addr.next=((TOS_pointer-2)%SIZE)+stack_offset
elif StackOP==STACK_ROT_THREE_1:
enable_stackpointer_increase.next=0
enable_stackpointer_deacrease.next=0
enable_stack_write_data.next=1
Data_to_REG.next=TOF_RAM_Data
stack_write_addr.next=((TOS_pointer-1)%SIZE)+stack_offset
stack_read_addr.next=((TOS_pointer-1)%SIZE)+stack_offset
#TOS_Data.next=TOS1_Data_RD
#TOS1_Data.next=TOS2_Data_RD
#TOS2_Data.next=TOS_Data_RD
#elif StackOP==STACK_ROT_FOUR: ##TODO
#TOS_Data.next=Stack_mem[int(TOS_pointer)]
# TOS1_Data.next=Stack_mem[int(TOS1_pointer)]
# TOS2_Data.next=Stack_mem[int(TOS2_pointer)]
elif StackOP==STACK_DUP_TOP:
enable_stackpointer_increase.next=1
enable_stackpointer_deacrease.next=0
elif StackOP==STACK_CMP:
enable_stackpointer_increase.next=1
enable_stackpointer_deacrease.next=0
else:
enable_stackpointer_increase.next=0
return seq_logic,comb_logic#,comb_logic2
"""def RS232_Module(iClk,iRst,iRX,oTX, iData,WriteEnable,oWrBuffer_full,oData,read_addr,oRx_addr,Clkfrequenz=12e6,Baudrate=38400,RX_BUFFER_LENGTH=8,TX_BUFFER_LENGTH=8):
##### Constants #####
CounterCycle=int(Clkfrequenz/Baudrate)
CounterCycle_half=int(Clkfrequenz/(Baudrate*2.0))
##### Signal definitions for Receiver Part ####
Receive_RAM=[Signal(intbv(0)[8:]) for i in range(RX_BUFFER_LENGTH)]
rx_counter=Signal(intbv(0,min=0,max=CounterCycle+2))
rx_currentData=Signal(intbv(0)[9:])
rx_bit_count=Signal(intbv(0,min=0,max=10))
rx_addr=Signal(intbv(0,min=0,max=RX_BUFFER_LENGTH))
rx_State=Signal(intbv(0,min=0,max=4))
##### Signal definitions for Transmitter Part ####
Transmit_RAM=[Signal(intbv(0)[8:]) for i in range(TX_BUFFER_LENGTH)]
tx_counter=Signal(intbv(0,min=0,max=CounterCycle+2))
tx_bit_count=Signal(intbv(0,min=0,max=11))
tx_addr=Signal(intbv(0,min=0,max=TX_BUFFER_LENGTH))
write_addr=Signal(intbv(0,min=0,max=TX_BUFFER_LENGTH))
tx_State=Signal(intbv(0,min=0,max=4))
SendREG=Signal(intbv(0)[10:])
sig_WrBuffer_full=Signal(bool(0))
@always_comb
def comb2_logic():
oWrBuffer_full.next=sig_WrBuffer_full
@always_comb
def comb_logic():
if ((write_addr+1)%TX_BUFFER_LENGTH)==tx_addr:
sig_WrBuffer_full.next=True
else:
sig_WrBuffer_full.next=False
@always(iClk.posedge,iRst.negedge)
def seq_logic():
if iRst==0:
###### Resets Receiver Part #####
rx_State.next=0
rx_counter.next=0
rx_currentData.next=0
rx_bit_count.next=0
rx_addr.next=0
oRx_addr.next=0
###### Resets Transmitter Part #####
tx_State.next=0
tx_addr.next=0
write_addr.next=0
SendREG.next=0
tx_counter.next=0
tx_bit_count.next=0
else:
oRx_addr.next=rx_addr
oData.next=Receive_RAM[read_addr]
oTX.next=1
################## Receiver Part ################
if rx_State==0: #IDLE STATE
if iRX==0:
rx_counter.next=rx_counter+1
else:
rx_counter.next=0
if rx_counter==CounterCycle_half:
rx_State.next=1
rx_counter.next=0
rx_bit_count.next=0
elif rx_State==1: #RECEIVING STATE
rx_counter.next=rx_counter+1
if rx_counter==0:
rx_currentData.next=concat(iRX,rx_currentData[9:1])
rx_bit_count.next=rx_bit_count+1
if rx_counter==CounterCycle:
rx_counter.next=0
if rx_bit_count==9:
rx_State.next=2
rx_counter.next=0
elif rx_State==2: #STOPBIT STATE
rx_counter.next=rx_counter+1
if rx_counter==CounterCycle:
rx_State.next=0
rx_counter.next=0
if iRX==1: #Stopbit is Received
Receive_RAM[rx_addr].next=rx_currentData[9:1]
rx_addr.next=(rx_addr+1)%RX_BUFFER_LENGTH
################## Transmitter Part ################
#### Writing Data to Transmit Buffer ####
#TODO Buffer full flag#
if WriteEnable and (not sig_WrBuffer_full):
Transmit_RAM[write_addr].next=iData
write_addr.next=(write_addr+1)%TX_BUFFER_LENGTH
#### Transmitting Statmachine ####
if tx_State==0:
if write_addr!=tx_addr:
tx_counter.next=0
tx_State.next=1
tx_bit_count.next=0
SendREG.next=concat(intbv(1)[1:],Transmit_RAM[tx_addr],intbv(0)[1:])
tx_addr.next=(tx_addr+1)%TX_BUFFER_LENGTH
elif tx_State==1: ### Send Bytes
oTX.next=SendREG[tx_bit_count]
tx_counter.next=tx_counter+1
if tx_counter==CounterCycle:
tx_bit_count.next=tx_bit_count+1
tx_counter.next=0
if tx_bit_count==9:
tx_State.next=0
return seq_logic,comb_logic,comb2_logic"""
import RS232_Norbo
def IOModule(clk,rst,dout,din,addr,we,\
PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,\
iRX,oTX, # iRX needs to initialized with 1 \
GLOBAL_CONTENT,WIDTH=32, \
BAUDRATE=38400,RX_BUFF_LEN=8,TX_BUFF_LEN=8,Clk_f=12e6):
Sync_in1_PORTA=Signal(intbv(0)[WIDTH:])
Sync_in2_PORTA=Signal(intbv(0)[WIDTH:])
Sync_in1_PORTB=Signal(intbv(0)[WIDTH:])
Sync_in2_PORTB=Signal(intbv(0)[WIDTH:])
INTERN_PORTC_OUT=Signal(intbv(0)[WIDTH:])
INTERN_PORTD_OUT=Signal(intbv(0)[WIDTH:])
glob_mem = [Signal(intbv(0,min=-2**(WIDTH-1),max=2**(WIDTH-1))) for i in range(len(GLOBAL_CONTENT))]
######RS232#########
##### Signal definitions #####
iData_RS232=Signal(intbv(0)[8:])
oData_RS232=Signal(intbv(0)[8:])
WriteEnable_RS232=Signal(bool(0))
oWrBuffer_full=Signal(bool(0))
read_addr_RS232=Signal(intbv(0,min=0,max=RX_BUFF_LEN))
reg_read_addr_RS232=Signal(intbv(0,min=0,max=RX_BUFF_LEN))
rx_addr_RS232=Signal(intbv(0,min=0,max=RX_BUFF_LEN))
##### Instanciate RS232 Module #####
rs232_instance=RS232_Norbo.RS232_Module(clk,rst,iRX,oTX, iData_RS232,WriteEnable_RS232, \
oWrBuffer_full,oData_RS232,read_addr_RS232,rx_addr_RS232,Clkfrequenz=Clk_f, \
Baudrate=BAUDRATE,RX_BUFFER_LENGTH=RX_BUFF_LEN,TX_BUFFER_LENGTH=TX_BUFF_LEN)
@always_comb
def rs232_read_buffer_addr():
if we and (addr==5):
read_addr_RS232.next=din[WIDTH:]%RX_BUFF_LEN
else:
read_addr_RS232.next=reg_read_addr_RS232
@always(clk.posedge,rst.negedge)
def IO_write_sync():
if rst==0:
INTERN_PORTC_OUT.next=0
INTERN_PORTD_OUT.next=0
for i in range(len(GLOBAL_CONTENT)):
glob_mem[int(i)].next=GLOBAL_CONTENT[i] ##TODO this must be a memory initialisation
else:
Sync_in1_PORTA.next=PORTA_IN
Sync_in2_PORTA.next=Sync_in1_PORTA
Sync_in1_PORTB.next=PORTB_IN
Sync_in2_PORTB.next=Sync_in1_PORTB
WriteEnable_RS232.next=0
if we:
if addr==2:
INTERN_PORTC_OUT.next=din[WIDTH:]
if addr==3:
INTERN_PORTD_OUT.next=din[WIDTH:]
if addr==4:
WriteEnable_RS232.next=1
iData_RS232.next=din[WIDTH:]
if addr==5:
reg_read_addr_RS232.next=din[WIDTH:]
if addr>=8:
glob_mem[int(addr-8)].next=din
#GLOBAL_CONTENT[int(addr-4)]
@always(clk.posedge)
def IO_read():
PORTC_OUT.next=INTERN_PORTC_OUT
PORTD_OUT.next=INTERN_PORTD_OUT
dout.next = 0
if addr==0:
dout.next = Sync_in2_PORTA[WIDTH:].signed()
if addr==1:
dout.next = Sync_in2_PORTB[WIDTH:].signed()
if addr==2:
dout.next = INTERN_PORTC_OUT[WIDTH:].signed()
if addr==3:
dout.next = INTERN_PORTD_OUT[WIDTH:].signed()
if addr==4:
dout.next = oData_RS232
if addr==5:
dout.next = reg_read_addr_RS232
if addr==6:
dout.next = rx_addr_RS232
if addr==7:
dout.next = oWrBuffer_full
if addr>=8:
dout.next = glob_mem[int(addr-8)]
return IO_write_sync,IO_read,rs232_instance,rs232_read_buffer_addr
def Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,iRX,oTX,CPU_PROGRAM_OPCODES=COMPLETE_PROGRAMM_OPCODES,CPU_PROGRAM_ARGS=COMPLETE_PROGRAMM_ARGS,CPU_CONSTANTS=CONSTANTS_MEM_CONTENT,CPU_GLOBALS=GLOBALS_MEM_CONTENT,CONST_FUNCTION_ADRESSES_START=GLOBAL_FUNCTION_ADRESSES_START,VAR_BITWIDTH=32,VAR_MEM_DEPTH=20,STACK_SIZE=GLOBAL_STACK_SIZE,OPCODE_ARG_MAX_VALUE=GLOBAL_OPCODE_ARG_MAX_VALUE,DEBUG_OUTPUT=False):
CONST_PROGRAMM_LENGTH=len(CPU_PROGRAM_OPCODES)
NUMBER_OF_SELECTS=4
ENUM_SEL_NONE,ENUM_SEL_VARIABLE,ENUM_SEL_CONST,ENUM_SEL_GLOBAL=range(NUMBER_OF_SELECTS)
StackTopSel=Signal(intbv(0,min=0,max=NUMBER_OF_SELECTS))
REG_StackTopSel=Signal(intbv(0,min=0,max=NUMBER_OF_SELECTS))
NUMBER_FROM_SELECTS=4
FROM_NONE,FROM_CONST,FROM_GLOBAL,FROM_VAR=range(NUMBER_FROM_SELECTS)
argnext_store=Signal(intbv(0,min=0,max=NUMBER_FROM_SELECTS))
REG_argnext_store=Signal(intbv(0,min=0,max=NUMBER_FROM_SELECTS))
#### helping signals
MAX_NUMBER_FUNCTION_ARGUMENTS=10 #TODO magic number
#EnableJump=Signal(bool(0))
Inc_ArgumentCount=Signal(bool(0))
Clear_ArgumentCount=Signal(bool(0))
REG_ArgumentCount=Signal(intbv(0,min=0,max=MAX_NUMBER_FUNCTION_ARGUMENTS+2))
JumpValue=Signal(intbv(0)[8:])
MAX_SUB_CYCLES=2
REG_sub_pc_count=Signal(intbv(0,min=0,max=MAX_SUB_CYCLES))
sub_pc_count_next=Signal(intbv(0,min=0,max=MAX_SUB_CYCLES))
Push_Programcounter=Signal(bool(0))
Pop_Programcounter=Signal(bool(0))
Old_ProgrammCounter=Signal(intbv(0,min=0,max=CONST_PROGRAMM_LENGTH+1))
REG_PC_offsetValue=Signal(intbv(0,min=0,max=CONST_PROGRAMM_LENGTH+1))
PC_offsetValue=Signal(intbv(0,min=0,max=CONST_PROGRAMM_LENGTH+1))
Old_PC_offsetValue=Signal(intbv(0,min=0,max=CONST_PROGRAMM_LENGTH+1))
Set_Variables_offset=Signal(bool(0))
#Return_Variables_offset=Signal(bool(0))
#### Programm Memory Signals
Opcode=Signal(intbv(0)[8:])
Arg1=Signal(intbv(0,min=0,max=OPCODE_ARG_MAX_VALUE+1))
REG_ProgramCounter=Signal(intbv(-1,min=-1,max=CONST_PROGRAMM_LENGTH+1))
#### Constants Memory Signals
ConstantsData=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1)))
ConstantsAddr=Signal(intbv(0,min=0,max=len(CPU_CONSTANTS)))
#### Programm Variables RAM Signals
Varibles_DataOut=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1))) #Signal(intbv(0)[VAR_BITWIDTH:])
Variables_DataIn=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1))) #Signal(intbv(0)[VAR_BITWIDTH:])
VariablesAddr=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
VariablesAddr_write_to_inst=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
VariablesAddr_read_to_inst=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
REG_max_Variables_address=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
Old_max_Variables_address=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
REG_Variables_addr_offset=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
Old_Variables_addr_offset=Signal(intbv(0,min=0,max=VAR_MEM_DEPTH))
Variables_we=Signal(bool(0))
#### Stack Signals
# STACK_SIZE
Stack_DataIn=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1))) #Signal(intbv(0)[VAR_BITWIDTH:])
StackValue0=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1))) #Signal(intbv(0)[VAR_BITWIDTH:])
StackOP=Signal(intbv(0,min=0,max=GLOBAL_NUMBERSTACK_OPS))
StackOP_CMPmode=Signal(intbv(0,min=0,max=6))
#### IO Module Signals
NR_IO_ADDRESSES=8 # TODO magic number
IO_MODULE_LENGTH_MAX=NR_IO_ADDRESSES+len(GLOBALS_MEM_CONTENT)+1
CONST_FUNCTION_ADRESSES_START # <-- is a parameter of the processor unit
IO_DataOut=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1))) #Signal(intbv(0)[VAR_BITWIDTH:])
IO_DataIn=Signal(intbv(0,min=-2**(VAR_BITWIDTH-1),max=2**(VAR_BITWIDTH-1))) #Signal(intbv(0)[VAR_BITWIDTH:])
IO_addr=Signal(intbv(0,min=0,max=IO_MODULE_LENGTH_MAX))
IO_we=Signal(bool(0))
####Variables RAM instantiation
VariablesRAM_inst=DP_RAM(Varibles_DataOut, Variables_DataIn, VariablesAddr_write_to_inst,VariablesAddr_read_to_inst, Variables_we, clk, WORD_SZ=VAR_BITWIDTH, DEPTH=VAR_MEM_DEPTH)
###Programm Code Memory instantiation
ProgrammCode_inst=ProgrammRAM(clk,rst,Opcode,Arg1,JumpValue,OPCODE_CONTENT=CPU_PROGRAM_OPCODES,OPCODE_ARGUMENTS_CONTENT=CPU_PROGRAM_ARGS)
###Constants memory instantiation
ConstantsRAM_inst=RAM(clk,ConstantsData,ConstantsAddr,CPU_CONSTANTS,WORD_SZ=VAR_BITWIDTH)
###The stack
TheStack_inst=Stack(clk,rst,StackValue0,Stack_DataIn,StackOP,StackOP_CMPmode, WORD_SZ=VAR_BITWIDTH,SIZE=STACK_SIZE)
###I/O Module instantiation
IOModule_inst=IOModule(clk,rst,IO_DataOut,IO_DataIn,IO_addr,IO_we,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,iRX,oTX,GLOBAL_CONTENT=CPU_GLOBALS,WIDTH=VAR_BITWIDTH)
CONST_PC_STACK_DEPTH=5 #Defines how many nasted function are possible TODO magic number
REG_pc_stack_addr=Signal(intbv(0,min=0,max=CONST_PC_STACK_DEPTH))
pc_steck_mem = [Signal(intbv(0,min=0,max=CONST_PROGRAMM_LENGTH+1)) for i in range(CONST_PC_STACK_DEPTH)]
pc_offsets_mem = [Signal(intbv(0,min=0,max=CONST_PROGRAMM_LENGTH+1)) for i in range(CONST_PC_STACK_DEPTH)]
max_var_addr_mem=[Signal(intbv(0,min=0,max=VAR_MEM_DEPTH)) for i in range(CONST_PC_STACK_DEPTH)]
@always(clk.posedge,rst.negedge)
def seq_logic():
if rst == 0:
##### REG_ProgramCounter Part ########
REG_ProgramCounter.next = -1 #TODO very not nice
##### END REG_ProgramCounter Part ########
REG_ArgumentCount.next=0
REG_max_Variables_address.next=0
REG_Variables_addr_offset.next=0
REG_pc_stack_addr.next=0
REG_PC_offsetValue.next=0
REG_StackTopSel.next=ENUM_SEL_NONE
REG_sub_pc_count.next=0
else:
if Inc_ArgumentCount==True:
REG_ArgumentCount.next=REG_ArgumentCount+1
if Clear_ArgumentCount==True:
REG_ArgumentCount.next=0
if VariablesAddr_write_to_inst>=REG_max_Variables_address:
REG_max_Variables_address.next=VariablesAddr_write_to_inst+1
#print "REG_max_Variables_address",REG_max_Variables_address
REG_StackTopSel.next=StackTopSel
REG_argnext_store.next=argnext_store
##### REG_ProgramCounter Part ########
#if EnableJump==True:
REG_ProgramCounter.next=JumpValue
#else:
# REG_ProgramCounter.next = REG_ProgramCounter+1
REG_PC_offsetValue.next=PC_offsetValue
##### END REG_ProgramCounter Part ########
REG_sub_pc_count.next=sub_pc_count_next
##### Programmm counter stack#######
if Push_Programcounter: # Set at CALL_FUNCTION
pc_steck_mem[int(REG_pc_stack_addr-1)].next=REG_ProgramCounter
pc_offsets_mem[int(REG_pc_stack_addr-1)].next=REG_PC_offsetValue
if Pop_Programcounter: # Set at RETURN_VALUE
REG_pc_stack_addr.next=REG_pc_stack_addr-1
REG_Variables_addr_offset.next=Old_Variables_addr_offset
REG_max_Variables_address.next=Old_max_Variables_address
#print "########returning REG_max_Variables_address:", REG_max_Variables_address,Old_max_Variables_address,Old_Variables_addr_offset
#####End Programmm counter stack#########
if Set_Variables_offset: # Set at LOAD_GLOBAL if a function address is loaded
REG_pc_stack_addr.next=REG_pc_stack_addr+1
max_var_addr_mem[int(REG_pc_stack_addr)].next=REG_max_Variables_address
REG_Variables_addr_offset.next=REG_max_Variables_address
#print "###########LOAD_GLOBAL",REG_Variables_addr_offset, REG_max_Variables_address,REG_ProgramCounter,JumpValue
#if Return_Variables_offset:
@always_comb
def comb_logic2():
VariablesAddr_write_to_inst.next=REG_Variables_addr_offset+VariablesAddr
#print "VariablesAddr",VariablesAddr, "REG_Variables_addr_offset",REG_Variables_addr_offset
Old_ProgrammCounter.next=0
Old_max_Variables_address.next=0
Old_Variables_addr_offset.next=0
Old_PC_offsetValue.next=0
if REG_pc_stack_addr>0:
Old_PC_offsetValue.next=pc_offsets_mem[int(REG_pc_stack_addr-1)]
Old_ProgrammCounter.next=pc_steck_mem[int(REG_pc_stack_addr-1)]
Old_max_Variables_address.next=max_var_addr_mem[int(REG_pc_stack_addr-1)]
if REG_pc_stack_addr>1:
Old_Variables_addr_offset.next=max_var_addr_mem[int(REG_pc_stack_addr-2)]
##### Opcode handling#############
@always_comb
def comb_logic():
sub_pc_count_next.next=0
VariablesAddr_read_to_inst.next=VariablesAddr_write_to_inst
#Enable_PC_offset.next=False
PC_offsetValue.next=REG_PC_offsetValue
Set_Variables_offset.next=False
#Return_Variables_offset.next=False
Push_Programcounter.next=False
Pop_Programcounter.next=False
Inc_ArgumentCount.next=False
Clear_ArgumentCount.next=False
#EnableJump.next=False
JumpValue.next=REG_ProgramCounter+1
ConstantsAddr.next=0
StackOP.next=STACK_NOP
StackOP_CMPmode.next=0
Stack_DataIn.next=0
Variables_we.next=False
VariablesAddr.next=0
Variables_DataIn.next=StackValue0
IO_we.next=False
IO_addr.next=0
IO_DataIn.next=StackValue0
StackTopSel.next=ENUM_SEL_NONE
if REG_StackTopSel==ENUM_SEL_CONST:
Stack_DataIn.next=ConstantsData
elif REG_StackTopSel==ENUM_SEL_GLOBAL:
Stack_DataIn.next=IO_DataOut
elif REG_StackTopSel==ENUM_SEL_VARIABLE:
Stack_DataIn.next=Varibles_DataOut
elif REG_StackTopSel==ENUM_SEL_NONE:
Stack_DataIn.next=0
argnext_store.next=FROM_NONE
if REG_argnext_store==FROM_GLOBAL:
VariablesAddr.next=REG_ArgumentCount-2
Variables_DataIn.next=IO_DataOut
Variables_we.next=True
elif REG_argnext_store==FROM_VAR:
VariablesAddr.next=REG_ArgumentCount-2
Variables_DataIn.next=Varibles_DataOut
Variables_we.next=True
elif REG_argnext_store==FROM_CONST:
VariablesAddr.next=REG_ArgumentCount-2
Variables_DataIn.next=ConstantsData
Variables_we.next=True
if Opcode==23: #dis.opmap['BINARY_ADD']: # 23,
StackOP.next=STACK_ADD
elif Opcode==64: #dis.opmap['BINARY_AND']: # 64,
StackOP.next=STACK_AND
elif Opcode==62: #dis.opmap['BINARY_LSHIFT']: #: 62,
StackOP.next=STACK_LSHIFT
elif Opcode==66: #dis.opmap['BINARY_OR']: #: 66,
StackOP.next=STACK_OR
elif Opcode==63: #dis.opmap['BINARY_RSHIFT']: #: 63,
StackOP.next=STACK_RSHIFT
elif Opcode==24: #dis.opmap['BINARY_SUBTRACT']: #: 24,
StackOP.next=STACK_SUB
elif Opcode==65: #dis.opmap['BINARY_XOR']: #: 65,
StackOP.next=STACK_XOR
elif Opcode==107: #dis.opmap['COMPARE_OP']: #: 107,
StackOP.next=STACK_CMP
StackOP_CMPmode.next=Arg1
elif Opcode==4: #dis.opmap[''DUP_TOP']: # 4
StackOP.next=STACK_DUP_TOP
elif Opcode==113: #dis.opmap['JUMP_ABSOLUTE'] : #: 113,
#EnableJump.next=True
JumpValue.next=Arg1+REG_PC_offsetValue
elif Opcode==110: #dis.opmap['JUMP_FORWARD']: #: 110,
#EnableJump.next=True
#print "JUMP_FORWARD"
JumpValue.next=REG_ProgramCounter+1+Arg1 #relative jump
elif Opcode==111: #dis.opmap['JUMP_IF_FALSE_OR_POP']: #: 111,
if StackValue0[1:0]==0:
#EnableJump.next=True
JumpValue.next=Arg1+REG_PC_offsetValue
else:
StackOP.next=STACK_POP
elif Opcode==112: #dis.opmap['JUMP_IF_TRUE_OR_POP']: #: 112,
if StackValue0[1:0]==1:
JumpValue.next=Arg1+REG_PC_offsetValue
#EnableJump.next=True
else:
StackOP.next=STACK_POP
elif Opcode==100: #dis.opmap['LOAD_CONST']: #: 100,
if REG_ArgumentCount==0:
StackOP.next=STACK_LOAD
StackTopSel.next=ENUM_SEL_CONST
ConstantsAddr.next=Arg1
else:
Inc_ArgumentCount.next=True
ConstantsAddr.next=Arg1
argnext_store.next=FROM_CONST
elif Opcode==124: #dis.opmap['LOAD_FAST']: #: 124, #TODO Split read and write address to support var arguments
if REG_ArgumentCount==0:
StackOP.next=STACK_LOAD
VariablesAddr.next=Arg1
StackTopSel.next=ENUM_SEL_VARIABLE
else:
Inc_ArgumentCount.next=True
VariablesAddr_read_to_inst.next=Old_Variables_addr_offset+Arg1
argnext_store.next=FROM_VAR
elif Opcode==116: #dis.opmap['LOAD_GLOBAL']: #116,
if Arg1>=CONST_FUNCTION_ADRESSES_START:
Inc_ArgumentCount.next=True
Set_Variables_offset.next=True
if REG_ArgumentCount==0: # load from global mem
StackOP.next=STACK_LOAD
IO_addr.next=Arg1
StackTopSel.next=ENUM_SEL_GLOBAL
else:
Inc_ArgumentCount.next=True
IO_addr.next=Arg1
argnext_store.next=FROM_GLOBAL
elif Opcode==131: #dis.opmap['CALL_FUNCTION']
#print "############### Call Function ##########"
Push_Programcounter.next=True
#Enable_PC_offset.next=True
JumpValue.next=StackValue0
PC_offsetValue.next=StackValue0 #Put on the stack with LOAD_GLOBAL
StackOP.next=STACK_POP
# The Function Arguments are not loaded over the stack
# they are written directly to the Variables RAM if the LOAD_GLOBAL argument is in the Function address range
Clear_ArgumentCount.next=True
elif Opcode==83: #dis.opmap['RETURN_VALUE']
#print "############### Return Function ##########"
#Enable_PC_offset.next=True
PC_offsetValue.next=Old_PC_offsetValue
JumpValue.next=Old_ProgrammCounter+1
Pop_Programcounter.next=True
#StackOP.next=STACK_POP_BLOCK
elif Opcode==97: #dis.opmap['STORE_GLOBAL']: 97,
IO_we.next=True
IO_addr.next=Arg1
StackOP.next=STACK_POP
elif Opcode==114: #dis.opmap['POP_JUMP_IF_FALSE']: #: 114,
StackOP.next=STACK_POP
if StackValue0[1:0]==0:
JumpValue.next=Arg1+REG_PC_offsetValue
#EnableJump.next=True
elif Opcode==115: #dis.opmap['POP_JUMP_IF_TRUE']: #: 115,
StackOP.next=STACK_POP
if StackValue0[1:0]==1:
JumpValue.next=Arg1+REG_PC_offsetValue
#EnableJump.next=True
elif Opcode==1: #dis.opmap['POP_TOP']
StackOP.next=STACK_POP
elif Opcode==5: #dis.opmap['ROT_FOUR']: #: 5,
StackOP.next=STACK_ROT_FOUR
elif Opcode==3: #dis.opmap['ROT_THREE']: #: 3,
if REG_sub_pc_count==0:
sub_pc_count_next.next=REG_sub_pc_count+1
JumpValue.next=REG_ProgramCounter
StackOP.next=STACK_ROT_THREE_0
if REG_sub_pc_count==1:
sub_pc_count_next.next=0
StackOP.next=STACK_ROT_THREE_1
elif Opcode==2: #dis.opmap['ROT_TWO']: #: 2,
StackOP.next=STACK_ROT_TWO
elif Opcode==125: #dis.opmap['STORE_FAST']: #: 125,
Variables_we.next=True
VariablesAddr.next=Arg1
StackOP.next=STACK_POP
elif Opcode==15: #dis.opmap['UNARY_INVERT']: #:15
StackOP.next=STACK_INVERT
elif Opcode==11: #dis.opmap['UNARY_NEGATIVE']: #: 11,
StackOP.next=STACK_NEGATIVE
elif Opcode==12: #dis.opmap['UNARY_NOT']: #: 12,
StackOP.next=STACK_NOT
elif Opcode==10: #dis.opmap['UNARY_POSITIVE']: #: 10,
StackOP.next=STACK_POSITIVE
elif Opcode==120: #dis.opmap['SETUP_LOOP']: # TODO?? #(explanation from python homepage) Pushes a block for a loop onto the block stack. The block spans from the current instruction with a size of delta bytes.
StackOP.next=STACK_SETUP_LOOP
#print "##########setup loop"
elif Opcode==87: #dis.opmap['POP_BLOCK']: # TODO?? dis.opmap['POP_BLOCK']
StackOP.next=STACK_POP_BLOCK
#print "##########pop block"
else:
StackOP.next=STACK_NOP
#raise ValueError("Unsuported Command:"+str(Opcode))
#if rst!=0:
print "Comand not supported:",Opcode
if DEBUG_OUTPUT:
import dis
cmp_op = dis.cmp_op
hasconst = dis.hasconst
hasname = dis.hasname
hasjrel = dis.hasjrel
haslocal = dis.haslocal
hascompare = dis.hascompare
@always(Opcode,Arg1)
def monitor_opcode():
instruction = (dis.opname[int(Opcode)]+" "+str(int(Opcode)), None, None, None)
if Opcode in hasconst:
instruction = (instruction[0],int(Arg1) ,'const=', CPU_CONSTANTS[Arg1])
elif Opcode in hasname:
#if Arg1>NR_IO_ADDRESSES:
# instruction = (instruction[0],Arg1 ,'global=', CPU_GLOBALS[Arg1])
#else:
instruction = (instruction[0],int(Arg1) ,None, None)
#print "Error: no name instruction is supported yet"
#raise StopSimulation
elif Opcode in hasjrel:
instruction = (instruction[0], int(Arg1),'addr=', REG_ProgramCounter+Arg1)
elif Opcode in haslocal:
instruction = (instruction[0], int(Arg1),'var=', int(Varibles_DataOut.val))
elif Opcode in hascompare:
instruction = (instruction[0], int(Arg1),'cmp=', cmp_op[Arg1])
print instruction
if DEBUG_OUTPUT:
return seq_logic,comb_logic,comb_logic2,VariablesRAM_inst,ProgrammCode_inst,ConstantsRAM_inst,TheStack_inst,IOModule_inst,monitor_opcode
else:
return seq_logic,comb_logic,comb_logic2,VariablesRAM_inst,ProgrammCode_inst,ConstantsRAM_inst,TheStack_inst,IOModule_inst #,monitor_opcode
def Processor_TESTBENCH():
WORD_SZ=8
rst, clk = [Signal(bool(0)) for i in range(2)]
PORTA_IN=Signal(intbv(0)[WORD_SZ:])
PORTB_IN=Signal(intbv(0)[WORD_SZ:])
PORTC_OUT=Signal(intbv(0)[WORD_SZ:])
PORTD_OUT=Signal(intbv(0)[WORD_SZ:])
iRX = Signal(bool(1))
oTX = Signal(bool(0))
#toVHDL(Processor,clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,iRX,oTX,VAR_BITWIDTH=WORD_SZ)
Processor_inst=Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,iRX,oTX,VAR_BITWIDTH=WORD_SZ,DEBUG_OUTPUT=False)
@always_comb
def uart_loopback():
iRX.next=oTX
@always(delay(10))
def clkgen():
clk.next = not clk
@instance
def stimulus():
print "Reseting ########"
rst.next=0
print "Setting PORTA_IN too 0 ########"
PORTA_IN.next=0
for i in range(3):
yield clk.negedge
print "Release Reset ########"
rst.next=1
for i in range(200):
yield clk.negedge
print "Setting PORTA_IN too 1 (PORTC bit 0 should toggle) ########"
PORTA_IN.next=1
for i in range(2000):
yield clk.negedge
print "Setting PORTA_IN too 0 (PORTC bit 0 should stop toggling) ########"
PORTA_IN.next=0
for i in range(70000):
yield clk.negedge
raise StopSimulation
@instance
def Monitor_PORTC():
print "\t\tPortC:",PORTC_OUT,"Binary:" ,bin(PORTC_OUT,WORD_SZ) ##TODO bin is not supported in simulation
while 1:
yield PORTC_OUT
print "\t\tPortC:",PORTC_OUT,"Binary:" ,bin(PORTC_OUT,WORD_SZ)
@instance
def Monitor_PORTD():
print "PortD:",PORTD_OUT
while 1:
yield PORTD_OUT
print "PortD:",PORTD_OUT
return clkgen,Processor_inst,stimulus,Monitor_PORTC,Monitor_PORTD,uart_loopback
def ClkSysClk(clk_intern):
@always(clk_intern)
def logic():
# do nothing here
pass
clk_intern.driven="wire"
__vhdl__="""OSCInst0: OSCH
-- synthesis translate_off
GENERIC MAP ( NOM_FREQ => "2.08" )
-- synthesis translate_on
PORT MAP (
STDBY=> '0',
OSC=> %(clk_intern)s);"""
return logic
def PicoBoard(iPushBn,rst,
iCap_btn1,iCap_btn2,iCap_btn3,iCap_btn4,
oLCD_COM0,oLCD_COM1,oLCD_COM2,oLCD_COM3,oLCD_5,oLCD_6,oLCD_7,oLCD_8,oLCD_9,oLCD_10,oLCD_11,oLCD_12,
iUart_rx,oUart_tx,
oSpi_sclk,oSpi_csn,oSpi_mosi,iSpi_miso,
ioScl,ioSda,
oI2CAlert,oEnAMP,oEnTempSPI,
Icc_analog_cmp_n,iIcc_analog_cmp_p,oIcc_analog_out,iIcco_analog_cmp_n,iIcco_analog_cmp_p,oIcco_analog_out,
iClk_USB,oUSBorBattout,oTouched1out):
WORD_SZ=8
#rst, clk = [Signal(bool(0)) for i in range(2)]
clk_intern=Signal(bool(0))
btn_rst=Signal(bool(0))
#nRst=Signal(bool(0))
PORTA_IN=Signal(intbv(0)[WORD_SZ:])
PORTB_IN=Signal(intbv(0)[WORD_SZ:])
PORTC_OUT=Signal(intbv(0)[WORD_SZ:])
PORTD_OUT=Signal(intbv(0)[WORD_SZ:])
iRX=Signal(bool(0))
oTX=Signal(bool(0))
#counter=Signal(intbv(0,min=0,max=12000000))
#tog=Signal(bool(0))
Processor_inst=Processor(iClk_USB,btn_rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,iRX,oTX,VAR_BITWIDTH=WORD_SZ,DEBUG_OUTPUT=False)
#@always(iClk_USB.posedge)
#def seqen_logic():
# counter.next=(counter+1)%12000000
# if counter==0:
# tog.next=not tog
# oUSBorBattout.next=tog
# Clk_inst=ClkSysClk(clk_intern)
#connect processor to outside world
@always_comb
def combo_logic():
PORTB_IN[0].next=iCap_btn1
PORTB_IN[1].next=iCap_btn2
PORTB_IN[3].next=iCap_btn3
PORTB_IN[4].next=iCap_btn4
iRX.next=iUart_rx
#PORTA_IN[0].next=iPushBn
btn_rst.next=iPushBn
oLCD_5.next=PORTC_OUT[0]
oLCD_6.next=PORTC_OUT[1]
oLCD_7.next=PORTC_OUT[2]
oLCD_8.next=PORTC_OUT[3]
oLCD_9.next=PORTC_OUT[4]
oLCD_10.next=PORTC_OUT[5]
oLCD_11.next=PORTC_OUT[6]
oLCD_12.next=PORTC_OUT[7]
oLCD_COM0.next=PORTD_OUT[0]
oLCD_COM1.next=PORTD_OUT[1]
oLCD_COM2.next=PORTD_OUT[2]
oLCD_COM3.next=PORTD_OUT[3]
oUart_tx.next=oTX
oSpi_sclk.next=0
oSpi_csn.next=0
oSpi_mosi.next=0
ioScl.next=0
ioSda.next=0
oI2CAlert.next=0
oEnAMP.next=0
oEnTempSPI.next=0
oIcc_analog_out.next=0
oIcco_analog_out.next=0
oTouched1out.next=PORTD_OUT[4]
oUSBorBattout.next=PORTD_OUT[5]
return Processor_inst,combo_logic#,seqen_logic #,Clk_inst
##################### convert pico Board to VHDL###################
NumberArguments=38
for i in range(NumberArguments):
code="A"+str(i)+"= Signal(bool(0))"
exec(code)
code="toVHDL(PicoBoard"
for i in range(NumberArguments):
code=code+",A"+str(i)
code=code+")"
exec(code)
##################### convert pico Board to VHDL###################
#toVHDL(Processor,clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,VAR_BITWIDTH=WORD_SZ)
#toVHDL(Processor_TESTBENCH)
tb = traceSignals(Processor_TESTBENCH)
#sim = Simulation(Processor_TESTBENCH())
sim = Simulation(tb)
sim.run()
#def convert():
# WORD_SZ=8
# DEPTH=16384
# we, clk = [Signal(bool(0)) for i in range(2)]
# dout = Signal(intbv(0)[WORD_SZ:])
# din = Signal(intbv(0)[WORD_SZ:])
# addr = Signal(intbv(0)[16:])
# toVHDL(RAM, dout, din, addr, we,clk,WORD_SZ,DEPTH)
#convert()
#def simulate(timesteps):
# tb = traceSignals(test_dffa)
# sim = Simulation(tb)
# sim.run(timesteps)
#simulate(20000)