myhdl-list Mailing List for MyHDL (Page 102)
Brought to you by:
jandecaluwe
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(14) |
Nov
(4) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(1) |
Feb
(10) |
Mar
(19) |
Apr
(14) |
May
(1) |
Jun
(4) |
Jul
(10) |
Aug
|
Sep
(2) |
Oct
(7) |
Nov
(17) |
Dec
(12) |
2005 |
Jan
(6) |
Feb
(10) |
Mar
(17) |
Apr
(10) |
May
(9) |
Jun
(5) |
Jul
(26) |
Aug
(34) |
Sep
(10) |
Oct
(38) |
Nov
(71) |
Dec
(74) |
2006 |
Jan
(20) |
Feb
(20) |
Mar
(7) |
Apr
(2) |
May
(13) |
Jun
|
Jul
|
Aug
(4) |
Sep
(37) |
Oct
(43) |
Nov
(30) |
Dec
(33) |
2007 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
(30) |
Jun
(9) |
Jul
(1) |
Aug
|
Sep
(8) |
Oct
(13) |
Nov
|
Dec
(4) |
2008 |
Jan
(13) |
Feb
(46) |
Mar
(25) |
Apr
(7) |
May
(20) |
Jun
(73) |
Jul
(38) |
Aug
(47) |
Sep
(24) |
Oct
(18) |
Nov
(9) |
Dec
(36) |
2009 |
Jan
(31) |
Feb
(24) |
Mar
(73) |
Apr
(13) |
May
(47) |
Jun
(28) |
Jul
(36) |
Aug
(2) |
Sep
(5) |
Oct
(8) |
Nov
(16) |
Dec
(29) |
2010 |
Jan
(34) |
Feb
(18) |
Mar
(18) |
Apr
(5) |
May
|
Jun
(24) |
Jul
(53) |
Aug
(3) |
Sep
(18) |
Oct
(33) |
Nov
(19) |
Dec
(15) |
2011 |
Jan
(9) |
Feb
(4) |
Mar
(39) |
Apr
(213) |
May
(86) |
Jun
(46) |
Jul
(22) |
Aug
(11) |
Sep
(78) |
Oct
(59) |
Nov
(38) |
Dec
(24) |
2012 |
Jan
(9) |
Feb
(22) |
Mar
(89) |
Apr
(55) |
May
(222) |
Jun
(86) |
Jul
(57) |
Aug
(32) |
Sep
(49) |
Oct
(69) |
Nov
(12) |
Dec
(35) |
2013 |
Jan
(67) |
Feb
(39) |
Mar
(18) |
Apr
(42) |
May
(79) |
Jun
(1) |
Jul
(19) |
Aug
(18) |
Sep
(54) |
Oct
(79) |
Nov
(9) |
Dec
(26) |
2014 |
Jan
(30) |
Feb
(44) |
Mar
(26) |
Apr
(11) |
May
(39) |
Jun
(1) |
Jul
(89) |
Aug
(15) |
Sep
(7) |
Oct
(6) |
Nov
(20) |
Dec
(27) |
2015 |
Jan
(107) |
Feb
(106) |
Mar
(130) |
Apr
(90) |
May
(147) |
Jun
(28) |
Jul
(53) |
Aug
(16) |
Sep
(23) |
Oct
(7) |
Nov
|
Dec
(16) |
2016 |
Jan
(86) |
Feb
(41) |
Mar
(38) |
Apr
(31) |
May
(37) |
Jun
(11) |
Jul
(1) |
Aug
(1) |
Sep
(3) |
Oct
(1) |
Nov
(5) |
Dec
(3) |
2017 |
Jan
|
Feb
(4) |
Mar
(2) |
Apr
(2) |
May
|
Jun
(3) |
Jul
(2) |
Aug
(2) |
Sep
(1) |
Oct
(2) |
Nov
(1) |
Dec
(1) |
2018 |
Jan
(1) |
Feb
(1) |
Mar
(7) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2019 |
Jan
(1) |
Feb
|
Mar
(2) |
Apr
(1) |
May
(1) |
Jun
(2) |
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
(3) |
Dec
|
2020 |
Jan
(1) |
Feb
(2) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
|
Dec
(3) |
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
(12) |
Dec
(11) |
2022 |
Jan
(7) |
Feb
(2) |
Mar
(1) |
Apr
|
May
|
Jun
(1) |
Jul
(3) |
Aug
(2) |
Sep
(1) |
Oct
|
Nov
|
Dec
(1) |
2023 |
Jan
|
Feb
(1) |
Mar
(1) |
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
2024 |
Jan
(1) |
Feb
(2) |
Mar
(4) |
Apr
(2) |
May
(2) |
Jun
(1) |
Jul
|
Aug
(1) |
Sep
(1) |
Oct
|
Nov
|
Dec
(2) |
2025 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Christopher F. <chr...@gm...> - 2012-03-12 13:59:08
|
On 3/12/2012 8:19 AM, Sébastien Bourdeauducq wrote: > Hi, > > A recurring (and well founded) comment on my Migen work was that some > sort of simulator integration would be important. It's there now, and I > would like to thank the people behind the RHINO project > (http://www.rhinoplatform.org/) for sponsoring this feature. > > You can read about it and see some examples in the last section of the > manual: > http://milkymist.org/Migen.pdf > > Send technical questions and comments to the Milkymist mailing list at > devel [AT] lists.milkymist.org and we will entertain them. > > Happy designing, > Sébastien > Sebastien, Why do you spam this mailing list? .chris |
From: Sébastien B. <seb...@mi...> - 2012-03-12 13:25:59
|
Hi, A recurring (and well founded) comment on my Migen work was that some sort of simulator integration would be important. It's there now, and I would like to thank the people behind the RHINO project (http://www.rhinoplatform.org/) for sponsoring this feature. You can read about it and see some examples in the last section of the manual: http://milkymist.org/Migen.pdf Send technical questions and comments to the Milkymist mailing list at devel [AT] lists.milkymist.org and we will entertain them. Happy designing, Sébastien |
From: Christopher F. <chr...@gm...> - 2012-03-06 12:03:38
|
On 3/6/12 5:34 AM, John Sager wrote: > Christopher Felton<chris.felton<at> gmail.com> writes: > > ... >> >> Couple things, If you want a single module that is an adder/subtractor >> you can directory add or subtract. >> >> def AdderSubtractor(clk, a,b,c, Subtract=False): >> assert len(a)>= max(len(b),len(c))+1 >> @always(clk.posedge) >> def hdl_add_sub(): >> if Subtract: >> c.next = a - b >> else: >> c.next = a + b >> >> return hdl_ad_sub >> >> The above is completely scalable for the different bit widths. You >> might not need to define a AdderSubtractor module just use '+' and '-' >> unless you are multiplexing the adder/subtractor in the datapath. >> > ... >> >> Regards, >> Chris > > In fact I started off with the if-then-else construct on the Subtract flag but I > thought that the xor/plus logic would be more efficient. I ran them both through > the Quartus II compiler (Cyclone III target) yesterday and I found that the > circuit design using if-then-else uses considerably less logic for the same > functionality (on the complete circuit which instantiates many add/subtract > functions). That was completely against my expectation, but then I'm a long-time > software guy just starting out with hardware design. > > To that end I'm finding Myhdl to be an excellent tool to help me get to grips > with it all. > > J > Awesome! I hope the adventure continues to be excellent. If you have any questions or issues feel free to post. Regards, Chris |
From: John S. <jo...@sa...> - 2012-03-06 11:34:52
|
Christopher Felton <chris.felton <at> gmail.com> writes: ... > > Couple things, If you want a single module that is an adder/subtractor > you can directory add or subtract. > > def AdderSubtractor(clk, a,b,c, Subtract=False): > assert len(a) >= max(len(b),len(c))+1 > @always(clk.posedge) > def hdl_add_sub(): > if Subtract: > c.next = a - b > else: > c.next = a + b > > return hdl_ad_sub > > The above is completely scalable for the different bit widths. You > might not need to define a AdderSubtractor module just use '+' and '-' > unless you are multiplexing the adder/subtractor in the datapath. > ... > > Regards, > Chris In fact I started off with the if-then-else construct on the Subtract flag but I thought that the xor/plus logic would be more efficient. I ran them both through the Quartus II compiler (Cyclone III target) yesterday and I found that the circuit design using if-then-else uses considerably less logic for the same functionality (on the complete circuit which instantiates many add/subtract functions). That was completely against my expectation, but then I'm a long-time software guy just starting out with hardware design. To that end I'm finding Myhdl to be an excellent tool to help me get to grips with it all. J |
From: Christopher F. <chr...@gm...> - 2012-03-04 20:20:40
|
On 3/4/12 11:37 AM, John Sager wrote: > Christopher Felton<chris.felton<at> gmail.com> writes: > >>> >>> Jan, >>> >>> Thanks for that. However it's a bit low level, really, having to >>> synthesise an adder from basic logic rather than using Verilog's >>> higher level operators. The useful thing in that was the >>> ConcatSignal(*x) Python parameter passing idiom, of which I wasn't >>> aware, which would have saved me the hack on _ShadowSignal.py >>> >>> John >>> >>> >> >> Wait, that's contradictory to this thread. If you don't want to >> represent low-level description (which is good) simply use "c = a+b" you >> don't need to worry about anything else. The synthesis tools will >> gladly create correct/valid adders. >> >> Regards, >> Chris >> > > The real question I asked was whether myhdl would support generating the > {n{flag}} construct to produce 'cleaner' Verilog. > > what I get out is something like > > wire [15:0] x; > > assign x[15] = flag; > assign x[14] = flag; > ... > assign x[1] = flag; > assign x[0] = flag; > > and then used in > > a<= b + c^x + flag > > I suppose I shouldn't really worry about what the Verilog looks like. My code > simulates correctly in both myhdl and co-simulated with Icarus now anyway. > > J The goal of MyHDL is not make "clean" looking Verilog/VHDL (as in clean to the human reader) but Verilog and VHDL are the intermediate formats that the syntehsizers understand (optimized for syntheized results). In an ideal flow the MyHDL created Verilog/VHDL would not need to be looked at (by a human). With that said the Verilog/VHDL is not obfuscated if it doesn't need to be. Couple things, If you want a single module that is an adder/subtractor you can directory add or subtract. def AdderSubtractor(clk, a,b,c, Subtract=False): assert len(a) >= max(len(b),len(c))+1 @always(clk.posedge) def hdl_add_sub(): if Subtract: c.next = a - b else: c.next = a + b return hdl_ad_sub The above is completely scalable for the different bit widths. You might not need to define a AdderSubtractor module just use '+' and '-' unless you are multiplexing the adder/subtractor in the datapath. Second, I think the problem here is trying to write the MyHDL in a Verilog form. Best I can tell from the question you want to find away to initialize a bit-vector, that is variable size, either set it to all 0s or all 1s. all 0s: vec = Signal(intbv(0)[N:]) all 1s: vec = Signal(intbv(2**N-1)[N:]) Or you could use the ConcatSignal or concat x = concat(*[intbv(1)[1:] for ii in range(N)]) or x = ConcatSignal(*[Signal(True) for ii in range(N)]) No hacking required :) Regards, Chris |
From: John S. <jo...@sa...> - 2012-03-04 17:37:40
|
Christopher Felton <chris.felton <at> gmail.com> writes: > > > > Jan, > > > > Thanks for that. However it's a bit low level, really, having to > > synthesise an adder from basic logic rather than using Verilog's > > higher level operators. The useful thing in that was the > > ConcatSignal(*x) Python parameter passing idiom, of which I wasn't > > aware, which would have saved me the hack on _ShadowSignal.py > > > > John > > > > > > Wait, that's contradictory to this thread. If you don't want to > represent low-level description (which is good) simply use "c = a+b" you > don't need to worry about anything else. The synthesis tools will > gladly create correct/valid adders. > > Regards, > Chris > The real question I asked was whether myhdl would support generating the {n{flag}} construct to produce 'cleaner' Verilog. what I get out is something like wire [15:0] x; assign x[15] = flag; assign x[14] = flag; ... assign x[1] = flag; assign x[0] = flag; and then used in a <= b + c^x + flag I suppose I shouldn't really worry about what the Verilog looks like. My code simulates correctly in both myhdl and co-simulated with Icarus now anyway. J > ------------------------------------------------------------------------------ > Virtualization & Cloud Management Using Capacity Planning > Cloud computing makes use of virtualization - but cloud computing > also focuses on allowing computing to be delivered as a service. > http://www.accelacomm.com/jaw/sfnl/114/51521223/ > |
From: Christopher F. <chr...@gm...> - 2012-03-04 14:30:22
|
On 3/4/12 1:27 AM, John Sager wrote: > Jan Coombs<jan.coombs_2009<at> murray-microft.co.uk> writes: > >> >> On 03/03/12 16:40, John Sager wrote: >> . . . >> > >> > Now the question: Is there any facility in Myhdl to generate the >> {n{Sub}} >> > construct, and with a correct simulation? >> >> http://rosettacode.org/wiki/Four_bit_adder#MyHDL >> >> The second code sample here is Jan D's, and looks good to me. >> >> Jan Coombs. >> > > Jan, > > Thanks for that. However it's a bit low level, really, having to > synthesise an adder from basic logic rather than using Verilog's > higher level operators. The useful thing in that was the > ConcatSignal(*x) Python parameter passing idiom, of which I wasn't > aware, which would have saved me the hack on _ShadowSignal.py > > John > > Wait, that's contradictory to this thread. If you don't want to represent low-level description (which is good) simply use "c = a+b" you don't need to worry about anything else. The synthesis tools will gladly create correct/valid adders. Regards, Chris |
From: Jan C. <jan...@mu...> - 2012-03-04 13:12:14
|
On 04/03/12 07:27, John Sager wrote: > Jan Coombs<jan.coombs_2009<at> murray-microft.co.uk> writes: > >> >> On 03/03/12 16:40, John Sager wrote: >> . . . >> > >> > Now the question: Is there any facility in Myhdl to generate the >> {n{Sub}} >> > construct, and with a correct simulation? >> >> http://rosettacode.org/wiki/Four_bit_adder#MyHDL >> >> The second code sample here is Jan D's, and looks good to me. >> >> Jan Coombs. >> > > Jan, > > Thanks for that. However it's a bit low level, really, having to > synthesise an adder from basic logic rather than using Verilog's > higher level operators. The useful thing in that was the > ConcatSignal(*x) Python parameter passing idiom, of which I wasn't > aware, which would have saved me the hack on _ShadowSignal.py Sorry, replace the three defs in with: def Multibit_Adder(a, b, s): @always_comb def add(): s.next = a + b return add This seems to sim & convert ok. It was late and I assumed that breaking the signals into individual bits would be necessary, but it is not. Jan Coombs. |
From: Norbo <Nor...@gm...> - 2012-03-04 12:08:43
|
Just got a bit further and i am now able to do function calls in the Python Hardware CPU, and a was able to reduce the logic usage of CPU a bit by shifting some registers into ram where the data needs an extra cycle be accessible. But still was able to maintain the one bytecode instruction per clk cycle execution. Now the cpu is able to execute python code like the following successfully (PORTA_IN,PORTB_IN and etc.. are the IO/Ports): With the following code the Cpu synthesises to approximatly 800 LUTS_4. (on lattice diamond 1.4 and Quartus web edition) I also needed to modify the bytecode a bit so that the functions are mapped correctly. Thereby i merge all the constants and all the globals of every function to a single place. (normaly every python function has its own constans memory and global name map) PREDEFINED_IO_ADDRESSES={'PORTA_IN':0,'PORTB_IN':1,'PORTC_OUT':2,'PORTD_OUT':3} #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 # 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 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: #or x>=20 and x<25: #both works PORTD_OUT=(2**7)+x else: PORTD_OUT=x a,b=b,a PORTD_OUT=a<<1 Tried it on hardware and i was able to blink an led on a lattic pico development board. With the following python code: (The Output pin was connected to the 5. pin of PORTD_OUT.) The Synthesis tools says that it can be run at 23 Mhz or so but i was running it at 12 MHz. PREDEFINED_IO_ADDRESSES={'PORTA_IN':0,'PORTB_IN':1,'PORTC_OUT':2,'PORTD_OUT':3} #need to start at 0 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 CPU_main(): global PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT while 1: PORTD_OUT=PORTD_OUT^16 wait(20) I just post the full code, right now its not very readable, ##################################### # 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} #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 # 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 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 ##### End of the main programm #### import MakeProcessorBytecode ProcessorCodeObject=MakeProcessorBytecode.MakeBytecode(CPU2_main,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 ############ 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 IOModule(clk,rst,dout,din,addr,we,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,GLOBAL_CONTENT,WIDTH=32): 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))] @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 if we: if addr==2: INTERN_PORTC_OUT.next=din[WIDTH:] elif addr==3: INTERN_PORTD_OUT.next=din[WIDTH:] elif addr>=4: glob_mem[int(addr-4)].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 =glob_mem[int(addr-4)] return IO_write_sync,IO_read def Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,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=4 # 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,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_ADD 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:]) toVHDL(Processor,clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,VAR_BITWIDTH=WORD_SZ) Processor_inst=Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,VAR_BITWIDTH=WORD_SZ,DEBUG_OUTPUT=False) @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(2000): 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 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:]) #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,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 #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=0 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) And the MakeProcessorBytecode Module: import dis ################# Reworking the bytecode, so that it better fits into the Processor (e.g Alignment issues)################### class MakeBytecode: def __init__(self,mainfunction,PredefinedIOAddresses,OtherGlobals): for Portname in PredefinedIOAddresses.keys(): OtherGlobals[Portname]=0 Unworked_functionArray={mainfunction.func_name:mainfunction} occuring_globals_dict=PredefinedIOAddresses Processed_functions_dict={} function_names_inorder=[] Function_offset=0 programm_dict={} while len(Unworked_functionArray)>0: funcname,currentfunction=Unworked_functionArray.popitem() Processed_functions_dict[funcname]=(Function_offset,currentfunction) #create function mapping in Programm Rom (start addresses of functions) function_names_inorder.append(funcname) theprogramm=tuple([ord(i) for i in currentfunction.func_code.co_code]) # count=0 new_count=0 REWORKED_GLOBAL_PROGRAMM_OPCODE=[] REWORKED_GLOBAL_PROGRAMM_ARG=[] Addressmap_old_new={} # create a seperate opcode and argument List (fits better in myhdl ram) # extend opcodes without argument with an 0 argument while 1: if count<len(theprogramm): REWORKED_GLOBAL_PROGRAMM_OPCODE.append(theprogramm[count]) Addressmap_old_new[count]=new_count if theprogramm[count]>=dis.HAVE_ARGUMENT: actual_Argument=(theprogramm[count+2]<<8)+theprogramm[count+1] REWORKED_GLOBAL_PROGRAMM_ARG.append(actual_Argument) if theprogramm[count]==dis.opmap['LOAD_GLOBAL']: if hasattr(OtherGlobals[currentfunction.func_code.co_names[actual_Argument]], '__call__'): # if GLOBAL_LOAD loads a function if not Processed_functions_dict.has_key(currentfunction.func_code.co_names[actual_Argument]): #if function is allready processed ##every function is just added once because it is a dictionary Unworked_functionArray[currentfunction.func_code.co_names[actual_Argument]]=OtherGlobals[currentfunction.func_code.co_names[actual_Argument]] count=count+3 else: REWORKED_GLOBAL_PROGRAMM_ARG.append(0) count=count+1 new_count=new_count+1 else: break Function_offset=Function_offset+len(REWORKED_GLOBAL_PROGRAMM_OPCODE) # next function will get next free Programm ROM Address # Readjust all absolute jump addresses for index,i in enumerate(REWORKED_GLOBAL_PROGRAMM_OPCODE): if i in dis.hasjabs: REWORKED_GLOBAL_PROGRAMM_ARG[index]=Addressmap_old_new[REWORKED_GLOBAL_PROGRAMM_ARG[index]] # Readjust relative jump addresses, for now only JUMP_FORWARD is changed count=0 while 1: if count<len(theprogramm): if theprogramm[count]>=dis.HAVE_ARGUMENT: actual_Argument=(theprogramm[count+2]<<8)+theprogramm[count+1] if theprogramm[count]==dis.opmap['JUMP_FORWARD']: #print count REWORKED_GLOBAL_PROGRAMM_ARG[Addressmap_old_new[count]]=Addressmap_old_new[count+3+actual_Argument]-Addressmap_old_new[count+3] count=count+3 else: count=count+1 else: break programm_dict[funcname]=(REWORKED_GLOBAL_PROGRAMM_OPCODE,REWORKED_GLOBAL_PROGRAMM_ARG) ## after this: Every Opcode and argument is at one address, Absolut jumps are corrected, and relative JUMP_FORWARD is corrected ########## end while len(Unworked_functionArray)>0: ######### #occuring_globals_dict=PREDEFINED_IO_ADDRESSES self.GLOBALS_MEM_CONTENT=[] if len(occuring_globals_dict)>0: globals_addr=max(occuring_globals_dict.values())+1 else: globals_addr=0 occuring_const_values_dict={} self.CONSTANTS_MEM_CONTENT=[] if len(occuring_const_values_dict)>0: const_addr=max(occuring_const_values_dict.values())+1 else: const_addr=0 ### Adjust and merge LOAD_GLOBAL, STORE_GLOBAL,LOAD_CONST , and Global_mem ##create shared GLOBALS_MEM_CONTENT and shared CONSTANTS_MEM_CONTENT ###merge constants (because python creates uniqe constants for every function) ###merge globals (introduce global_var_mem, only for function calling and global constants) ###rework global addresses (LOAD_GLOBAL, STORE_GLOBAL) ###rework const addresses (LOAD_CONST) ###rework absolut jump addresses of functions (LOAD_GLOBAL) ###only constant arguments are supported, or dual ported var mem is needed list_Load_global_when_fcall=[] for funcname in function_names_inorder: currentprogramm_opcodes=programm_dict[funcname][0] currentprogramm_arg=programm_dict[funcname][1] for index,i in enumerate(currentprogramm_opcodes): if i==dis.opmap['LOAD_CONST']: const_value=Processed_functions_dict[funcname][1].func_code.co_consts[currentprogramm_arg[index]] if type(const_value)==type(0): if not occuring_const_values_dict.has_key(const_value): self.CONSTANTS_MEM_CONTENT.append(const_value) occuring_const_values_dict[const_value]=const_addr const_addr=const_addr+1 currentprogramm_arg[index]=occuring_const_values_dict[const_value] elif type(const_value)==type(None) and currentprogramm_arg[index]==0: pass else: print "Error: Only integers are suportted, Type is:",type(const_value) if i==dis.opmap['LOAD_GLOBAL'] or i==dis.opmap['STORE_GLOBAL']: global_name=Processed_functions_dict[funcname][1].func_code.co_names[currentprogramm_arg[index]] if type(OtherGlobals[global_name])==type(0): ##needs to be an integer if not occuring_globals_dict.has_key(global_name): occuring_globals_dict[global_name]=globals_addr self.GLOBALS_MEM_CONTENT.append(OtherGlobals[global_name]) globals_addr=globals_addr+1 currentprogramm_arg[index]=occuring_globals_dict[global_name] elif i==dis.opmap['LOAD_GLOBAL'] and hasattr(OtherGlobals[global_name], '__call__'): list_Load_global_when_fcall.append((funcname,global_name,index)) else: print "Error: Only integers are suportted, Type is:",type(OtherGlobals[global_name]) #store changes programm_dict[funcname]=(currentprogramm_opcodes,currentprogramm_arg) #print occuring_globals_dict #print "ops:",currentprogramm_opcodes #print "args:",currentprogramm_arg self.GLOBAL_FUNCTION_ADRESSES_START=globals_addr ##### rework LOAD_GLOBAL arguments when functions are loaded and add the function address to the GLOBALS_MEM_CONTENT ##### functions addresses are the highest addresses in the GLOBAL_MEM,GLOBAL_FUNCTION_ADRESSES_START is used in the core ##### to decide wheter it is a normal LOAD_GLOBAL or if the LOAD global loads a function for basefuncname,callfunctionname,index in list_Load_global_when_fcall: if not occuring_globals_dict.has_key(callfunctionname): occuring_globals_dict[callfunctionname]=globals_addr self.GLOBALS_MEM_CONTENT.append(Processed_functions_dict[callfunctionname][0]) ### add the offset address of the function, to the GLOBAL memory globals_addr=globals_addr+1 programm_dict[basefuncname][1][index]=occuring_globals_dict[callfunctionname] #currentprogramm_arg[index]=occuring_globals_dict[func_name] #### stitch programms of the induvidual functions together self.COMPLETE_PROGRAMM_OPCODES=[] self.COMPLETE_PROGRAMM_ARGS=[] for FuncName in function_names_inorder: self.COMPLETE_PROGRAMM_OPCODES.extend(programm_dict[FuncName][0]) self.COMPLETE_PROGRAMM_ARGS.extend(programm_dict[FuncName][1]) self.GLOBAL_STACK_SIZE=0 for offset,func_object in Processed_functions_dict.itervalues(): self.GLOBAL_STACK_SIZE=max(func_object.func_code.co_stacksize,self.GLOBAL_STACK_SIZE) ## myhdl only works with tuples self.GLOBAL_STACK_SIZE=self.GLOBAL_STACK_SIZE if len(self.GLOBALS_MEM_CONTENT)==0: self.GLOBALS_MEM_CONTENT=(0,) #needs to be a tuple of integers else: self.GLOBALS_MEM_CONTENT=tuple(self.GLOBALS_MEM_CONTENT) self.CONSTANTS_MEM_CONTENT=tuple(self.CONSTANTS_MEM_CONTENT) self.COMPLETE_PROGRAMM_OPCODES=tuple(self.COMPLETE_PROGRAMM_OPCODES) self.COMPLETE_PROGRAMM_ARGS=tuple(self.COMPLETE_PROGRAMM_ARGS) self.GLOBAL_OPCODE_ARG_MAX_VALUE=max(self.COMPLETE_PROGRAMM_ARGS) #####end class MakeProzesserByteCode ##################### |
From: John S. <jo...@sa...> - 2012-03-04 07:28:01
|
Jan Coombs <jan.coombs_2009 <at> murray-microft.co.uk> writes: > > On 03/03/12 16:40, John Sager wrote: > . . . > > > > Now the question: Is there any facility in Myhdl to generate the > {n{Sub}} > > construct, and with a correct simulation? > > http://rosettacode.org/wiki/Four_bit_adder#MyHDL > > The second code sample here is Jan D's, and looks good to me. > > Jan Coombs. > Jan, Thanks for that. However it's a bit low level, really, having to synthesise an adder from basic logic rather than using Verilog's higher level operators. The useful thing in that was the ConcatSignal(*x) Python parameter passing idiom, of which I wasn't aware, which would have saved me the hack on _ShadowSignal.py John |
From: Jan C. <jan...@mu...> - 2012-03-03 22:12:17
|
On 03/03/12 16:40, John Sager wrote: . . . > > Now the question: Is there any facility in Myhdl to generate the {n{Sub}} > construct, and with a correct simulation? http://rosettacode.org/wiki/Four_bit_adder#MyHDL The second code sample here is Jan D's, and looks good to me. Jan Coombs. |
From: John S. <jo...@sa...> - 2012-03-03 17:15:17
|
The standard logic expression for an adder/subtractor is a = b + c^d + Sub where d is a vector of length len(c) and where each bit takes the value of the Sub signal. In Verilog this would be a <= b + c ^ {n{Sub}} + Sub where n is len(c) and a, b & c are signed quantities. I've managed to do something similar in Myhdl (v0.7) as follows def foo(clk, a, b, c, Sub): x=[] for i in range(len(c)): x.append(Sub) # Sub is a Signal vec = ConcatSignal(x) @always(clk.posedge) def bar(): a.next = b + (c.signed()^vec.signed()) + Sub return bar Note that I had to hack on _ShadowSignal.py to enable ConcatSignal to take a list of signals as the sole parameter as well as the normal way - I need to be able to change the vector length for different instantiations of the adder/subtractor. This will simulate correctly, but the Verilog produced is a bit baroque, and I haven't yet simulated it, though it looks OK. Essentially 'vec' is a wire of width len(c) and there are then len(c) assignment statements to assign Sub to each bit. Now the question: Is there any facility in Myhdl to generate the {n{Sub}} construct, and with a correct simulation? John Sager john <at> sager <dot> me <dot> uk |
From: Christopher L. <loz...@fr...> - 2012-02-23 21:41:57
|
Well I have wanted to do a parallel language on MyHDL for a while now, but I was not able to find an application. Where is the money? In fast financial applications! The problem is that I do not know anyone in that industry. I do not understand the industry. I need to go to a conference to get educated. Here is the high performance computing conference in the Financial Industry in New York in September. http://www.flaggmgmt.com/hpc/index.html Is anyone else interested in going? -- Regards Christopher Lozinski Check out my iPhone apps TextFaster and EmailFaster http://textfaster.com Expect a paradigm shift. http://MyHDL.org |
From: Norbo <Nor...@gm...> - 2012-02-21 20:15:20
|
> I do not understand why the realVals array (list ofsignals) is used > since only one element is used at a time. yeah it deosnt realy makes sense if only one element is used at a time, except for the case where you want to have read access to a constant then some time later override this data with some other value. (which would actually be like a ram access where the ram content is initialized, i have seen a post where jan wrote that he already had this code but he removed it because not every synthesis tool supported it at that time, or is there a limitation with verilog, i think vhdl should do fine now) > I believe the limitation you are trying to demonstrate is when the tuple > (ROM) access is mixed in other statements, instead of being its own > statement, i.e. rather than a separate generator to describe the ROM it > is embedded in the statements directly, e.g. > @always_comb > def hld_output(): > outData.next = inData*Table[int(dataIndex)] > For this second case to be convertible the converting code needs to do > some extra work which it does not and it is not clear if it should. The > conversion code will need to do the same conversion as the previous > (above) example, hence it will have to infer more. This has beendebated > in the past (level of inference) and there are differentopinions on the > level of inference that should be supported. Another way to do this in myhdl to avoid an "deeper level of inference" would be to use, instead of the Table[] (which is a tuple of ints), a explicit declared signal array where the initial values of the signal array are set to the values of the tuple, like this: signal_array=[Signal(intbv(Table[i],min=min(Table),max=max(Table)+1)) for i in range(len(Table))] an then use the signal_array in every statement where the access is mixed with other statements, e.g. @always_comb def hld_output(): outData.next = inData*signal_array[int(dataIndex)] + signal_array[int(dataIndex+1)] #.....etc This is actually working fine in myhdl simulation. The conversion to vhdl and verilog succeeds also without error or warning. but the signal_array in the vhdl code doesnt gets initialized with the Table values and outData will never get the corresponding data. So the actual workaround i am currently using is adding this code, but i think this could be a obstacle for some synthesis tools and for me it doesn't seams very neat, since it could be simply made obsolete. @always_comb def comb_logic(): for i in range(len(Table)): signal_array[int(i)].next=Table[int(i)] Ok here is the full code where i am using this workaround: (a ultra generic fir filter) ################################################################################################################ from myhdl import * def Combinatorical_adder(out,in1,in2): @always_comb def cc_logic(): out.next=in1+in2 return cc_logic ## NR_PARALLELS must be a natural divider of len(COEFFS) def Generic_FIR_filter(clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS,COEFFS): NR_COEFFS=len(COEFFS) coeffs_signal_array=[Signal(intbv(COEFFS[i],min=min(COEFFS),max=max(COEFFS)+1)) for i in range(NR_COEFFS)] reg_Shift_array=[Signal(intbv(0,min=inData.min,max=inData.max)) for i in range(NR_COEFFS)] reg_count=Signal(intbv(0,min=0,max=len(COEFFS))) add_conection=[Signal(intbv(0,min=outData.min,max=outData.max)) for i in range(NR_PARALLELS)] #TODO data range reg_mult_result=[Signal(intbv(0,min=outData.min,max=outData.max)) for i in range(NR_PARALLELS)] #TODO data range reg_accumulation=Signal(intbv(0,min=outData.min,max=outData.max)) reg_run_enable=Signal(bool(0)) Data_valid=Signal(bool(0)) reg_next_run_enable=Signal(bool(0)) addup_insts=[None]*NR_PARALLELS for i in range(NR_PARALLELS): if i==(NR_PARALLELS-1): addup_insts[i]=Combinatorical_adder(add_conection[i],reg_mult_result[i],0) else: addup_insts[i]=Combinatorical_adder(add_conection[i],reg_mult_result[i],add_conection[i+1]) @always(clk.posedge,rst.negedge) def seq_logic(): if rst==0: reg_count.next=0 for i in range(NR_COEFFS): reg_Shift_array[i].next=0 for i in range(NR_PARALLELS): reg_mult_result[i].next=0 reg_run_enable.next=0 Data_valid.next=0 else: outData_valid.next=Data_valid if inData_enable: #should not be enabled before data is valid reg_Shift_array[0].next=inData for i in range(NR_COEFFS-1): reg_Shift_array[int(i+1)].next=reg_Shift_array[int(i)] reg_run_enable.next=True reg_accumulation.next=0 Data_valid.next=False outData_valid.next=False if reg_run_enable: for i in range(NR_PARALLELS): reg_mult_result[int(i)].next=reg_Shift_array[int(i+reg_count)]*coeffs_signal_array[int(i+reg_count)] if reg_count==(NR_COEFFS-NR_PARALLELS): reg_count.next=0 Data_valid.next=True reg_run_enable.next=False else: reg_count.next=reg_count+NR_PARALLELS Data_valid.next=False if reg_next_run_enable: reg_accumulation.next=reg_accumulation+add_conection[0] reg_next_run_enable.next=reg_run_enable @always_comb def output_logic(): outData.next=reg_accumulation #### current workaround, ###### for i in range(NR_COEFFS): coeffs_signal_array[int(i)].next=COEFFS[int(i)] ############################################## return seq_logic,addup_insts ,output_logic #real_alu_insts,imag_alu_insts, comb_logic,seq_logic from pylab import * import scipy.signal as signal def TESTBENCH_XX(): ## Filter design COEFF_WIDTH=10 NR_COEFFS = 60 a = signal.firwin(NR_COEFFS, cutoff = 0.4, window = "hamming") filter_coefficients=tuple([int(i*2**COEFF_WIDTH) for i in a]) ## instanciation clk=Signal(bool(0)) rst=Signal(bool(0)) inData_enable=Signal(bool(0)) outData_valid=Signal(bool(0)) inData=Signal(intbv(0,min=-10,max=10)) outData=Signal(intbv(0,min=-20000,max=20000)) toVerilog(Generic_FIR_filter,clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS=3,COEFFS=filter_coefficients) dut_inst=Generic_FIR_filter(clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS=3,COEFFS=filter_coefficients) step_response=[] clock_counter=Signal(intbv(0)) @always(delay(10)) def clkgen(): clk.next = not clk clock_counter.next=clock_counter+1 @instance def stimulus(): rst.next=0 yield clk yield clk rst.next=1 yield clk yield clk #test step responce inData.next=0 inData_enable.next=1 for i in range(NR_COEFFS): yield clk.posedge inData_enable.next=0 yield clk.posedge print "wait for outData_valid" yield outData_valid step_response.append(int(outData)) yield clk.negedge inData.next=1 inData_enable.next=1 subplot(211) plot(step_response) ##step_response of HDL filter subplot(212) plot(cumsum(filter_coefficients)) ##step_response of the real filter print "Testbench Cycles:",clock_counter/2 show() raise StopSimulation return stimulus,clkgen,dut_inst sim = Simulation(TESTBENCH_XX()) sim.run() ########################################################################################### greetings Norbo |
From: Norbo <Nor...@gm...> - 2012-02-21 20:12:58
|
> I do not understand why the realVals array (list ofsignals) is used > since only one element is used at a time. yeah it deosnt realy makes sense if only one element used at a time, except for the case where you probably want to have read access to a constant mixed into another expression and then at some time later overide this data with some other value. (which would actually be like a ram access where the ram content is initialized, i have seen a post where jan wrote that he already had this code but he removed it because not every synthesis tool supported it at that time, or is there a limitation with verilog, i think vhdl should do fine now) > I believe the limitation you are trying to demonstrate is when the tuple > (ROM) access is mixed in other statements, instead of being its own > statement, i.e. rather than a separate generator to describe the ROM it > is embedded in the statements directly, e.g. > @always_comb > def hld_output(): > outData.next = inData*Table[int(dataIndex)] > For this second case to be convertible the converting code needs to do > some extra work which it does not and it is not clear if it should. The > conversion code will need to do the same conversion as the previous > (above) example, hence it will have to infer more. This has beendebated > in the past (level of inference) and there are differentopinions on the > level of inference that should be supported. Another way to do this in myhdl to avoid an "deeper level of inference" would be to use instead of the Table[] which is a tuple of ints a explicit declared signal array where the initial values of the signal array are set to the valus of the tuple, like this: signal_array=[Signal(intbv(Table[i],min=min(Table),max=max(Table)+1)) for i in range(len(Table))] an then use the signal_array in every statement where the access is mixed with other statements, e.g. @always_comb def hld_output(): outData.next = inData*signal_array[int(dataIndex)] + signal_array[int(dataIndex+1)] #.....etc This is actually working fine in myhdl simulation. The conversion to vhdl and verilog succeeds also without error or warning. but the signal_array in the vhdl code doesnt gets initialized with the Table values and outData will never get the corresponding data. So the actual workaround i am currently using is adding this code, but i think this could be a obstacle for some synthesis tools and for me it doesn't seams very neat, since it could be simply made obsolete. @always_comb def comb_logic(): for i in range(len(Table)): signal_array[int(i)].next=Table[int(i)] Ok here is the full code where i am using this workaround: (a ultra generic fir filter) ################################################################################################################ from myhdl import * def Combinatorical_adder(out,in1,in2): @always_comb def cc_logic(): out.next=in1+in2 return cc_logic ## NR_PARALLELS must be a natural divider of len(COEFFS) def Generic_FIR_filter(clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS,COEFFS): NR_COEFFS=len(COEFFS) coeffs_signal_array=[Signal(intbv(COEFFS[i],min=min(COEFFS),max=max(COEFFS)+1)) for i in range(NR_COEFFS)] reg_Shift_array=[Signal(intbv(0,min=inData.min,max=inData.max)) for i in range(NR_COEFFS)] reg_count=Signal(intbv(0,min=0,max=len(COEFFS))) add_conection=[Signal(intbv(0,min=outData.min,max=outData.max)) for i in range(NR_PARALLELS)] #TODO data range reg_mult_result=[Signal(intbv(0,min=outData.min,max=outData.max)) for i in range(NR_PARALLELS)] #TODO data range reg_accumulation=Signal(intbv(0,min=outData.min,max=outData.max)) reg_run_enable=Signal(bool(0)) Data_valid=Signal(bool(0)) reg_next_run_enable=Signal(bool(0)) addup_insts=[None]*NR_PARALLELS for i in range(NR_PARALLELS): if i==(NR_PARALLELS-1): addup_insts[i]=Combinatorical_adder(add_conection[i],reg_mult_result[i],0) else: addup_insts[i]=Combinatorical_adder(add_conection[i],reg_mult_result[i],add_conection[i+1]) @always(clk.posedge,rst.negedge) def seq_logic(): if rst==0: reg_count.next=0 for i in range(NR_COEFFS): reg_Shift_array[i].next=0 for i in range(NR_PARALLELS): reg_mult_result[i].next=0 reg_run_enable.next=0 Data_valid.next=0 else: outData_valid.next=Data_valid if inData_enable: #should not be enabled before data is valid reg_Shift_array[0].next=inData for i in range(NR_COEFFS-1): reg_Shift_array[int(i+1)].next=reg_Shift_array[int(i)] reg_run_enable.next=True reg_accumulation.next=0 Data_valid.next=False outData_valid.next=False if reg_run_enable: for i in range(NR_PARALLELS): reg_mult_result[int(i)].next=reg_Shift_array[int(i+reg_count)]*coeffs_signal_array[int(i+reg_count)] if reg_count==(NR_COEFFS-NR_PARALLELS): reg_count.next=0 Data_valid.next=True reg_run_enable.next=False else: reg_count.next=reg_count+NR_PARALLELS Data_valid.next=False if reg_next_run_enable: reg_accumulation.next=reg_accumulation+add_conection[0] reg_next_run_enable.next=reg_run_enable @always_comb def output_logic(): outData.next=reg_accumulation #### current workaround, ###### for i in range(NR_COEFFS): coeffs_signal_array[int(i)].next=COEFFS[int(i)] ############################################## return seq_logic,addup_insts ,output_logic #real_alu_insts,imag_alu_insts, comb_logic,seq_logic from pylab import * import scipy.signal as signal def TESTBENCH_XX(): ## Filter design COEFF_WIDTH=10 NR_COEFFS = 60 a = signal.firwin(NR_COEFFS, cutoff = 0.4, window = "hamming") filter_coefficients=tuple([int(i*2**COEFF_WIDTH) for i in a]) ## instanciation clk=Signal(bool(0)) rst=Signal(bool(0)) inData_enable=Signal(bool(0)) outData_valid=Signal(bool(0)) inData=Signal(intbv(0,min=-10,max=10)) outData=Signal(intbv(0,min=-20000,max=20000)) toVerilog(Generic_FIR_filter,clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS=3,COEFFS=filter_coefficients) dut_inst=Generic_FIR_filter(clk,rst,inData,inData_enable,outData,outData_valid,NR_PARALLELS=3,COEFFS=filter_coefficients) step_response=[] clock_counter=Signal(intbv(0)) @always(delay(10)) def clkgen(): clk.next = not clk clock_counter.next=clock_counter+1 @instance def stimulus(): rst.next=0 yield clk yield clk rst.next=1 yield clk yield clk #test step responce inData.next=0 inData_enable.next=1 for i in range(NR_COEFFS): yield clk.posedge inData_enable.next=0 yield clk.posedge print "wait for outData_valid" yield outData_valid step_response.append(int(outData)) yield clk.negedge inData.next=1 inData_enable.next=1 subplot(211) plot(step_response) ##step_response of HDL filter subplot(212) plot(cumsum(filter_coefficients)) ##step_response of the real filter print "Testbench Cycles:",clock_counter/2 show() raise StopSimulation return stimulus,clkgen,dut_inst sim = Simulation(TESTBENCH_XX()) sim.run() ########################################################################################### greetings Norbo |
From: Christopher F. <chr...@gm...> - 2012-02-20 12:03:48
|
On 2/18/2012 3:05 PM, Norbo wrote: > About: (More general support of indexed constants) > http://www.myhdl.org/doku.php/dev:tasks > ok this post maybe gets a bit long, but it may be helpful to further > eliminate this conversion limitation: > > i first present a simple myhdl example which is victim to such an > conversion limitation. > then i show three slightly different ways how it can be implemented in > vhdl (i dont no verilog). > > the myhdl example: > > ########################################################################## > from myhdl import * > > def somedut(inData,out_data,data_index,LENGTH): > TWIDDEL_WIDTH=10 > real_Vals=[Signal(intbv(0,min=-2000,max=2000)) for i in range(LENGTH)] > Table=tuple([i for i in range(LENGTH)]) > > @always_comb > def comb_logic(): > for i in range(LENGTH): > real_Vals[i].next=inData*Table[i] ###this line cannot be > converted to vhdl > @always_comb > def output_logic(): > out_data.next=real_Vals[data_index] > > return comb_logic,output_logic #real_alu_insts,imag_alu_insts, > comb_logic,seq_logic > Norbo, For this particular example, the description can be changed so that it does convert. I do not understand why the realVals array (list of signals) is used since only one element is used at a time. def SomeDut(inData, outData, dataIndex, LENGTH=4): Table = tuple([ii for ii in range(LENGTH)]) tableVal = Signal(intbv(0, min=-2000, max=2000)) @always_comb def hdl_get_table_value(): tableVal.next = Table[int(dataIndex)] @always_comb def hld_output(): outData.next = inData*tableVal return hld_output, hdl_get_table_value I believe the limitation you are trying to demonstrate is when the tuple (ROM) access is mixed in other statements, instead of being its own statement, i.e. rather than a separate generator to describe the ROM it is embedded in the statements directly, e.g. @always_comb def hld_output(): outData.next = inData*Table[int(dataIndex)] For this second case to be convertible the converting code needs to do some extra work which it does not and it is not clear if it should. The conversion code will need to do the same conversion as the previous (above) example, hence it will have to infer more. This has been debated in the past (level of inference) and there are different opinions on the level of inference that should be supported. Regards, Chris |
From: Norbo <Nor...@gm...> - 2012-02-18 21:06:04
|
About: (More general support of indexed constants) http://www.myhdl.org/doku.php/dev:tasks ok this post maybe gets a bit long, but it may be helpful to further eliminate this conversion limitation: i first present a simple myhdl example which is victim to such an conversion limitation. then i show three slightly different ways how it can be implemented in vhdl (i dont no verilog). the myhdl example: ########################################################################## from myhdl import * def somedut(inData,out_data,data_index,LENGTH): TWIDDEL_WIDTH=10 real_Vals=[Signal(intbv(0,min=-2000,max=2000)) for i in range(LENGTH)] Table=tuple([i for i in range(LENGTH)]) @always_comb def comb_logic(): for i in range(LENGTH): real_Vals[i].next=inData*Table[i] ###this line cannot be converted to vhdl @always_comb def output_logic(): out_data.next=real_Vals[data_index] return comb_logic,output_logic #real_alu_insts,imag_alu_insts, comb_logic,seq_logic def TESTBENCH_XX(): LENGTH=100 clk=Signal(bool(0)) inData=Signal(intbv(0,min=-10,max=10)) out0=Signal(intbv(0,min=-2000,max=2000)) index=Signal(intbv(0,min=0,max=100)) toVHDL(somedut,inData,out0,index,LENGTH) dut_inst=somedut(inData,out0,index,LENGTH) @always(delay(10)) def clkgen(): clk.next = not clk @instance def stimulus(): index.next=0 inData.next=0 inData.next=1 for i in range(LENGTH): yield clk index.next=i inData.next=2 for i in range(LENGTH): yield clk index.next=i raise StopSimulation @instance def Monitor(): #print "\t\tPortC:",PORTC_OUT,"Binary:" ,bin(PORTC_OUT,WORD_SZ) while 1: yield out0 print "out0=",out0 return dut_inst,Monitor,stimulus,clkgen sim = Simulation(TESTBENCH_XX()) sim.run() ########################################################################## The Error is: myhdl.ConversionError: in file general_rom.py, line 13: Object type is not supported in this context: Table, <type 'tuple'> ########################################################################## Possible (by altera quartus synthesis able) ways it could be implemented in vhdl: The one with the function is proposed on http://www.myhdl.org/doku.php/dev:tasks (More general support of indexed constants) ############################################################################## -- File: TESTBENCH.vhd -- Generated by MyHDL 0.7 -- Date: Sat Feb 18 19:09:25 2012 library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use std.textio.all; use work.pck_myhdl_07.all; entity TESTBENCH is port ( clk : in std_logic; inData: in signed (4 downto 0); out_data: out signed (7 downto 0); data_index: in signed (7 downto 0) ); end entity TESTBENCH; architecture MyHDL of TESTBENCH is type t_array_dut_inst_real_Vals is array(0 to 16) of signed (15 downto 0); signal dut_inst_real_Vals: t_array_dut_inst_real_Vals; type t_array_dut_test is array(0 to 16) of signed (4 downto 0); ---- 1. solution (solution 1 and 2 is basically the same but in sulotion 1 the content of the array is built ---- programtically) function init_mem return t_array_dut_test is variable temp_mem : t_array_dut_test; begin for i in t_array_dut_test'range loop temp_mem(i) := to_signed(i, 5); end loop; return temp_mem; end; signal dut_inst_test: t_array_dut_test:=init_mem; --or signal dut_inst_test: t_array_dut_test:=init_mem; ---- 2. solution, directly initialize the array signal dut_inst_test2: t_array_dut_test:=(0=> "00000", 1=> "00001", 2=> "00010", 3=> "00011", 4=> "00100", 5=> "00101", 6=> "00110", 7=> "00111", 8=> "01000", 9=> "01001", 10=> "01010", 11=> "01011", 12=> "01100", 13=> "01101", 14=> "01110", 15=> "01111", others => "10000"); ---- 3. solution same as Rom in myhdl, but from a function function ValueSelect(dut_inst_RomAddr: in integer) return signed is variable dut_inst_RomData : signed (4 downto 0); begin case dut_inst_RomAddr is when 0 => dut_inst_RomData := "00000"; --attention : instead of <= when 1 => dut_inst_RomData := "00001"; when 2 => dut_inst_RomData := "00010"; when 3 => dut_inst_RomData := "00011"; when 4 => dut_inst_RomData := "00100"; when 5 => dut_inst_RomData := "00101"; when 6 => dut_inst_RomData := "00110"; when 7 => dut_inst_RomData := "00111"; when 8 => dut_inst_RomData := "01000"; when 9 => dut_inst_RomData := "01001"; when 10 => dut_inst_RomData := "01010"; when 11 => dut_inst_RomData := "01011"; when 12 => dut_inst_RomData := "01100"; when 13 => dut_inst_RomData := "01101"; when 14 => dut_inst_RomData := "01110"; when 15 => dut_inst_RomData := "01111"; when others => dut_inst_RomData := "10000"; end case; return dut_inst_RomData; end; begin -- combinatorial TESTBENCH_DUT_INST_COMB_LOGIC: process ( inData,dut_inst_test) is begin for i in 0 to 16 loop dut_inst_real_Vals(i) <= (resize(inData, 11) * dut_inst_test(i)); --dut_inst_test2(i)); or ValueSelect(i)); end loop; end process TESTBENCH_DUT_INST_COMB_LOGIC; -- clocked --TESTBENCH_DUT_INST_COMB_LOGIC: process ( clk) is --begin --if rising_edge(clk) then -- for i in 0 to 16 loop -- dut_inst_real_Vals(i) <= (resize(inData, 11) * ValueSelect(i)); --dut_inst_test2(i)); or ValueSelect(i)); -- end loop; -- end if; --end process TESTBENCH_DUT_INST_COMB_LOGIC; out_data <= resize(dut_inst_real_Vals(to_integer(data_index)), 8); end architecture MyHDL; ############################################################################## greetings Norbo |
From: Christopher F. <chr...@gm...> - 2012-02-17 13:06:58
|
On 2/16/2012 12:12 AM, Shakthi Kannan wrote: > Hi, > > --- On Wed, Feb 15, 2012 at 7:08 PM, Christopher Felton > <chr...@gm...> wrote: > | Jan D already started an open-task list, this could be > | the start of the project list (http://www.myhdl.org/doku.php/dev:tasks, > | this page looks like it needs updating). > \-- > > Yes. myhdl is already available in Fedora and Fedora Electronic Lab. > > $ sudo yum install python-myhdl > > SK > Thanks! I have update the status as completed. Regards, Chris |
From: Shakthi K. <sha...@gm...> - 2012-02-16 06:12:22
|
Hi, --- On Wed, Feb 15, 2012 at 7:08 PM, Christopher Felton <chr...@gm...> wrote: | Jan D already started an open-task list, this could be | the start of the project list (http://www.myhdl.org/doku.php/dev:tasks, | this page looks like it needs updating). \-- Yes. myhdl is already available in Fedora and Fedora Electronic Lab. $ sudo yum install python-myhdl SK -- Shakthi Kannan http://www.shakthimaan.com |
From: Christopher F. <chr...@gm...> - 2012-02-15 13:38:58
|
On 2/15/2012 5:08 AM, Sébastien Bourdeauducq wrote: > I would love to be wrong, but I consider GSoC to be a mere waste of time: > * lots of paperwork and boring questions to answer. > * high chance of rejection (and even after you've spent so much time > filling in their crap, all you get is an automated message). > * especially since I believe most GSoC curators have not touched HDLs > and never will. > * mediocre quality code often gets written. > * keeping students in the project after GSoC ends is difficult. > > Just my personal opinion. I got Milkymist rejected twice and mentored > one project, and now I do not want to hear about GSoC again. > > Sébastien > > > On 02/15/2012 12:00 PM, Norbo wrote: >> Just an idea: >> whats about trying to participate with myhdl at Google's Summer of Code >> 2012? >> >> http://www.google-melange.com/gsoc/homepage/google/gsoc2012 I general, I would of thought that it would be a great idea. Especially, if you pick a specific topic like "MyHDL Python3 support". But I have no experience with GSoC and appreciate Sebastien's input; that it can be some work with low probability of success. But I don't see how it can hurt to apply (other than the cost of someones time). Jan D already started an open-task list, this could be the start of the project list (http://www.myhdl.org/doku.php/dev:tasks, this page looks like it needs updating). One successful method might be to solicit for applicants in local Universities. It might take some extra effort to encourage students if we want the effort to be successful. Regards, Chris |
From: Sébastien B. <seb...@mi...> - 2012-02-15 11:14:12
|
I would love to be wrong, but I consider GSoC to be a mere waste of time: * lots of paperwork and boring questions to answer. * high chance of rejection (and even after you've spent so much time filling in their crap, all you get is an automated message). * especially since I believe most GSoC curators have not touched HDLs and never will. * mediocre quality code often gets written. * keeping students in the project after GSoC ends is difficult. Just my personal opinion. I got Milkymist rejected twice and mentored one project, and now I do not want to hear about GSoC again. Sébastien On 02/15/2012 12:00 PM, Norbo wrote: > Just an idea: > whats about trying to participate with myhdl at Google's Summer of Code > 2012? > > http://www.google-melange.com/gsoc/homepage/google/gsoc2012 |
From: Norbo <Nor...@gm...> - 2012-02-15 11:00:33
|
Just an idea: whats about trying to participate with myhdl at Google's Summer of Code 2012? http://www.google-melange.com/gsoc/homepage/google/gsoc2012 |
From: Christopher L. <loz...@fr...> - 2012-02-06 15:56:26
|
On 2/6/12 7:27 AM, Christopher Felton wrote: > You are right, it might be a little difficult to create a wiki page > right now. You can still send a request but it might be awhile before A second person with root privileges would be a really good idea, and protect us all against the risk of something happening to Jan Decaluwe. -- Regards Christopher Lozinski Check out my iPhone apps TextFaster and EmailFaster http://textfaster.com Expect a paradigm shift. http://MyHDL.org |
From: Christopher F. <chr...@gm...> - 2012-02-06 12:28:07
|
On 2/6/2012 4:44 AM, Norbo wrote: > Yeah, creating a wiki page would be nice, but is this possible, since Jan > Decaluwe is unfortunately right now out of business. > > The Site says: > > """How to get an account: > > To request an account, please send an email to Jan Decaluwe. Please add > some info that demonstrates your experience level with MyHDL. """ > > > greetings > Norbo > You are right, it might be a little difficult to create a wiki page right now. You can still send a request but it might be awhile before it is acknowledged. Regards, Chris |
From: Norbo <Nor...@gm...> - 2012-02-06 10:45:05
|
Yeah, creating a wiki page would be nice, but is this possible, since Jan Decaluwe is unfortunately right now out of business. The Site says: """How to get an account: To request an account, please send an email to Jan Decaluwe. Please add some info that demonstrates your experience level with MyHDL. """ greetings Norbo |