myhdl-list Mailing List for MyHDL (Page 103)
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
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
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 |
From: garyr <ga...@fi...> - 2012-02-05 17:34:03
|
FYI - a recently published book on microprocessor design and Verilog. http://www.cc-webshop.com/ ----- Original Message ----- From: "Christopher Felton" <chr...@gm...> To: <myh...@li...> Sent: Saturday, February 04, 2012 2:11 PM Subject: Re: [myhdl-list] Python Hardware Processor > Norbo, > > If you like you can create a project page on the MyHDL wiki space. Or > you might want to share the code via BitBucket or GitHub. > > Regards, > Chris > |
From: Christopher F. <chr...@gm...> - 2012-02-04 22:12:20
|
Norbo, If you like you can create a project page on the MyHDL wiki space. Or you might want to share the code via BitBucket or GitHub. Regards, Chris On 2/4/12 7:48 AM, Norbo wrote: > To show where i am at: > ##################################### > # File: Core.py > # Author: Norbert Feurle > # Date: 4.2.2012 > # > # Description: Python Hardware Processor > # This Code implements a Hardware CPU in myhdl. The code for the cpu is > directly written in python > # and since the hardware description is also in python, the programmcode > is automatically into the design > # The cool thing is that by this approach only memory and stack hardware > is allocated in Hardware which is > # really needed. Simulation of the code on the cpu running is no problem. > (only python needed!) > # The bytecode of python is executed at the cpu at one instruction per > cycle > # By now only simple bytecode instructions are supported > # You can simply instantiate more Hardware CPUs on an FPGA with different > program code to make it run parallel > # > # License: Pro life licence. > # You are not allowed to 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 beings at > an unacceptable rate, or build hardware > # with it where te 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 > ################################################################################################# > > > > ######################################################################################## > #### Limitations: > #### no lists, no dicts no tuples, no float, no complex numbers, > #### no classmembers,no function calls, no multiplication, no exeptions, > no for x in xxx:, etc. > ######################################################################################## > ### What is supported: > ### ints(with x bits), no other python types > ### simple if and while and assignments > ### Operators: +, ^ , |,&. - (minus doesent work yet becaus i never used > signed (big TODO)) > ### Simple Digital IO with PORTs > ### And of corse some bugs > ######################################################################################## > > ##### The main programm for the python hardware porcessor to execute #### > def CPU_main(): > ## Reserves for IO Module ### > global PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT > PORTA_IN=0 #needs to bee here to reserve the right addresses (0 is > written to nowhere) > PORTB_IN=0 > PORTC_OUT=0 > PORTD_OUT=0 > ################# > x=0 > while 1: > x=x+1 > if PORTA_IN==1: > PORTC_OUT= PORTC_OUT^1 > if x<20: > PORTD_OUT=x > elif x>=20 and x<25: > PORTD_OUT=2**30+x > else: > PORTD_OUT=x > ##### End of the main programm #### > > > from myhdl import * > import math > import dis > HAVE_ARGUMENT=dis.HAVE_ARGUMENT > GLOBAL_PROGRAM=tuple([ord(i) for i in CPU_main.func_code.co_code]) + > (0,0,) #because arguments are also read > GLOBAL_CONSTANTS=(0,)+CPU_main.func_code.co_consts[1:] # because constant > None is on address 0 but cpu only supports int > GLOBAL_STACK_SIZE=CPU_main.func_code.co_stacksize > > GLOBAL_NUMBERSTACK_OPS=19 > 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,STACK_DUP_TOP=range(GLOBAL_NUMBERSTACK_OPS) > > > def RAM(dout, din, addr, we, clk, WORD_SZ=8, DEPTH=16384): > """ > > """ > mem = [Signal(intbv(0)[WORD_SZ:]) for i in range(DEPTH)] > > @always(clk.posedge) > def write(): > if we: > mem[int(addr)].next = din > > @always_comb > def read(): > dout.next = mem[int(addr)] > > return write,read > > > def ROM(dout,addr,CONTENT): > @always_comb > def rom_logic(): > dout.next= CONTENT[int(addr)] > > return rom_logic > > def ProgrammROM(Opcode,Arg1,Arg2,addr,CONTENT): > @always_comb > def progrom_logic(): > Opcode.next= CONTENT[int(addr)] > Arg1.next= CONTENT[int(addr+1)] > Arg2.next= CONTENT[int(addr+2)] > > return progrom_logic > > def > Stack(clk,rst,TopData_Out,Data_In,StackOP,CMPmode,WORD_SZ=32,SIZE=GLOBAL_STACK_SIZE): > Stack_mem = [Signal(intbv(0)[WORD_SZ:]) for i in range(SIZE)] > > Next_TSO_Data=Signal(intbv(0)[WORD_SZ:]) > TOS_Data=Signal(intbv(0)[WORD_SZ:]) > TOS1_Data=Signal(intbv(0)[WORD_SZ:]) > TOS2_Data=Signal(intbv(0)[WORD_SZ:]) > > TOS_Data_RD=Signal(intbv(0)[WORD_SZ:]) > TOS1_Data_RD=Signal(intbv(0)[WORD_SZ:]) > TOS2_Data_RD=Signal(intbv(0)[WORD_SZ:]) > > TOS_pointer_next=Signal(intbv(0,min=0,max=SIZE)) > TOS_pointer= Signal(intbv(0,min=0,max=SIZE)) > TOS1_pointer= Signal(intbv(0,min=0,max=SIZE)) > TOS2_pointer= Signal(intbv(0,min=0,max=SIZE)) > #TOS3_pointer= Signal(intbv(0,min=0,max=SIZE)) > > enable_stackpointer_increase=Signal(bool(0)) > enable_stackpointer_deacrease=Signal(bool(0)) > > @always(clk.posedge,rst.negedge) > def seq_logic(): > if rst == 0: > TOS_pointer_next.next=0 > TOS_pointer.next=0 > TOS1_pointer.next=0 > TOS2_pointer.next=0 > #TOS3_pointer.next=0 > for indexer in range(SIZE): > Stack_mem[int(indexer)].next=0 > else: > if enable_stackpointer_increase: > TOS_pointer_next.next=(TOS_pointer_next+1)% SIZE > TOS_pointer.next=TOS_pointer_next > TOS1_pointer.next=TOS_pointer > TOS2_pointer.next=TOS1_pointer > if enable_stackpointer_deacrease: > if TOS2_pointer==0: > TOS2_pointer.next=SIZE-1 > else: > TOS2_pointer.next=TOS2_pointer-1 > > TOS1_pointer.next=TOS2_pointer > TOS_pointer.next=TOS1_pointer > TOS_pointer_next.next=TOS_pointer > #Stackpointer.next=Stackpointer_next > > #attention if stacksize is to smalll the lower one gets overwritten > #so the ordering is important > # TODO: stacksize==1 would not work > Stack_mem[int(TOS2_pointer)].next=TOS2_Data > Stack_mem[int(TOS1_pointer)].next=TOS1_Data > Stack_mem[int(TOS_pointer)].next=TOS_Data > Stack_mem[int(TOS_pointer_next)].next=Next_TSO_Data > > > > @always_comb > def comb_logic(): > Next_TSO_Data.next=Stack_mem[int(TOS_pointer_next)] > TOS_Data.next=Stack_mem[int(TOS_pointer)] > TOS1_Data.next=Stack_mem[int(TOS1_pointer)] > TOS2_Data.next=Stack_mem[int(TOS2_pointer)] > > enable_stackpointer_increase.next=1 > enable_stackpointer_deacrease.next=0 > > if StackOP==STACK_NOP: > enable_stackpointer_increase.next=0 > elif StackOP==STACK_ADD: > Next_TSO_Data.next=TOS1_Data_RD+TOS_Data_RD > elif StackOP==STACK_POSITIVE: #??? > Next_TSO_Data.next=TOS_Data_RD > elif StackOP==STACK_NOT: > Next_TSO_Data.next=TOS_Data_RD > elif StackOP==STACK_NEGATIVE: > Next_TSO_Data.next=-TOS_Data_RD > elif StackOP==STACK_INVERT: > Next_TSO_Data.next=~TOS_Data_RD > elif StackOP==STACK_RSHIFT: > Next_TSO_Data.next=TOS1_Data_RD>>TOS_Data_RD > elif StackOP==STACK_LSHIFT: > Next_TSO_Data.next=TOS1_Data_RD<<TOS_Data_RD > elif StackOP==STACK_AND: > Next_TSO_Data.next=TOS1_Data_RD&TOS_Data_RD > elif StackOP==STACK_SUB: > Next_TSO_Data.next=TOS1_Data_RD-TOS_Data_RD > elif StackOP==STACK_OR: > Next_TSO_Data.next=TOS1_Data_RD|TOS_Data_RD > elif StackOP==STACK_XOR: > Next_TSO_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_LOAD: > Next_TSO_Data.next=Data_In > > elif StackOP==STACK_ROT_TWO: > enable_stackpointer_increase.next=0 > TOS_Data.next=TOS1_Data_RD > TOS1_Data.next=TOS_Data_RD > elif StackOP==STACK_ROT_THREE: > enable_stackpointer_increase.next=0 > 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: > Next_TSO_Data.next=TOS_Data_RD > elif StackOP==STACK_CMP: > if CMPmode==0: #operator< > if TOS1_Data_RD<TOS_Data_RD: > Next_TSO_Data.next=1 > else: > Next_TSO_Data.next=0 > if CMPmode==1: #operator<= > if TOS1_Data_RD<=TOS_Data_RD: > Next_TSO_Data.next=1 > else: > Next_TSO_Data.next=0 > if CMPmode==2: #operator == > if TOS1_Data_RD==TOS_Data_RD: > Next_TSO_Data.next=1 > else: > Next_TSO_Data.next=0 > if CMPmode==3: #operator != > if TOS1_Data_RD!=TOS_Data_RD: > Next_TSO_Data.next=1 > else: > Next_TSO_Data.next=0 > if CMPmode==4: #operator> > if TOS1_Data_RD>TOS_Data_RD: > Next_TSO_Data.next=1 > else: > Next_TSO_Data.next=0 > if CMPmode==5: #operator>= > if TOS1_Data_RD>=TOS_Data_RD: > Next_TSO_Data.next=1 > else: > Next_TSO_Data.next=0 > else: > enable_stackpointer_increase.next=0 > > > > @always_comb > def comb_logic2(): > TOS_Data_RD.next=Stack_mem[int(TOS_pointer)] > TOS1_Data_RD.next=Stack_mem[int(TOS1_pointer)] > TOS2_Data_RD.next=Stack_mem[int(TOS2_pointer)] > TopData_Out.next=Stack_mem[int(TOS_pointer)] > > return seq_logic,comb_logic,comb_logic2 > > def > IOModule(clk,rst,dout,din,addr,we,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,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:]) > @always(clk.posedge,rst.negedge) > def IO_write_sync(): > if rst==0: > INTERN_PORTC_OUT.next=0 > INTERN_PORTD_OUT.next=0 > 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 > elif addr==3: > INTERN_PORTD_OUT.next=din > > > @always_comb > 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 > if addr==1: > dout.next = Sync_in2_PORTB > if addr==2: > dout.next = INTERN_PORTC_OUT > if addr==3: > dout.next = INTERN_PORTD_OUT > > return IO_write_sync,IO_read > > > def > Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,CPU_PROGRAM=GLOBAL_PROGRAM,CPU_CONSTANTS=GLOBAL_CONSTANTS,VAR_BITWIDTH=32,VAR_DEPTH=20,STACK_SIZE=GLOBAL_STACK_SIZE): > > > #### helping signals > EnableJump=Signal(bool(0)) > JumpValue=Signal(intbv(0)[8:]) > > #### Programm Memory Signals > Opcode=Signal(intbv(0)[8:]) > Arg1=Signal(intbv(0)[8:]) > Arg2=Signal(intbv(0)[8:]) > ProgramCounter=Signal(intbv(0,min=0,max=len(CPU_main.func_code.co_code))) > > #### Constants Memory Signals > ConstantsData=Signal(intbv(0)[VAR_BITWIDTH:]) > ConstantsAddr=Signal(intbv(0,min=0,max=len(CPU_CONSTANTS))) > > #### Programm Variables RAM Signals > Varibles_DataOut=Signal(intbv(0)[VAR_BITWIDTH:]) > Variables_DataIn=Signal(intbv(0)[VAR_BITWIDTH:]) > VariablesAddr=Signal(intbv(0,min=0,max=VAR_DEPTH)) > Variables_we=Signal(bool(0)) > > #### Stack Signals > # STACK_SIZE > Stack_DataIn=Signal(intbv(0)[VAR_BITWIDTH:]) > StackValue0=Signal(intbv(0)[VAR_BITWIDTH:]) > StackOP=Signal(intbv(0,min=0,max=GLOBAL_NUMBERSTACK_OPS)) > StackOP_CMPmode=Signal(intbv(0,min=0,max=len(dis.cmp_op))) > > #### IO Module Signals > IO_MODULE_STARTADDRESSES=4 > #IO_MODULE_ADDRESBITS=int(math.log(IO_MODULE_STARTADDRESSES,2)+1)-1 > IO_DataOut=Signal(intbv(0)[VAR_BITWIDTH:]) > IO_DataIn=Signal(intbv(0)[VAR_BITWIDTH:]) > IO_addr=Signal(intbv(0,min=0,max=IO_MODULE_STARTADDRESSES)) > IO_we=Signal(bool(0)) > > ####Variables RAM instantiation > VariablesRAM_inst=RAM(Varibles_DataOut, Variables_DataIn, > VariablesAddr, Variables_we, clk, WORD_SZ=VAR_BITWIDTH, DEPTH=VAR_DEPTH) > > ###Programm Code Memory instantiation > ProgrammCode_inst=ProgrammROM(Opcode,Arg1,Arg2,ProgramCounter,CPU_PROGRAM) > > ###Constants memory instantiation > ConstantsROM_inst=ROM(ConstantsData,ConstantsAddr,CPU_CONSTANTS) > > ###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,WIDTH=VAR_BITWIDTH) > > @always(clk.posedge,rst.negedge) > def seq_logic(): > if rst == 0: > ##### ProgramCounter Part ######## > ProgramCounter.next = 0 > ##### END ProgramCounter Part ######## > > else: > ##### ProgramCounter Part ######## > if > EnableJump==True:#StackValue0==bool(1)#Opcode==dis.opmap['POP_JUMP_IF_FALSE'] > or Opcode==dis.opmap['POP_JUMP_IF_TRUE'] > ProgramCounter.next=JumpValue > else: > if Opcode>= HAVE_ARGUMENT: > ProgramCounter.next = ProgramCounter+3 > else: > ProgramCounter.next = ProgramCounter+1 > ##### END ProgramCounter Part ######## > > ##### Opcode handling############# > @always_comb > def comb_logic(): > > JumpValue.next=0 > EnableJump.next=False > > 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 > > 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 > elif Opcode==110: #dis.opmap['JUMP_FORWARD']: #: 110, > EnableJump.next=True > JumpValue.next=ProgramCounter+3+Arg1 > elif Opcode==111: #dis.opmap['JUMP_IF_FALSE_OR_POP']: #: 111, > if StackValue0==0: > EnableJump.next=True > JumpValue.next=Arg1 > elif Opcode==112: #dis.opmap['JUMP_IF_TRUE_OR_POP']: #: 112, > if StackValue0==1: > JumpValue.next=Arg1 > EnableJump.next=True > else: > StackOP.next=STACK_POP > elif Opcode==100: #dis.opmap['LOAD_CONST']: #: 100, > StackOP.next=STACK_LOAD > Stack_DataIn.next=ConstantsData > ConstantsAddr.next=Arg1 > elif Opcode==124: #dis.opmap['LOAD_FAST']: #: 124, > StackOP.next=STACK_LOAD > VariablesAddr.next=Arg1 > Stack_DataIn.next=Varibles_DataOut > elif Opcode==116: #dis.opmap['LOAD_GLOBAL']: 116, > StackOP.next=STACK_LOAD > IO_addr.next=Arg1 > Stack_DataIn.next=IO_DataOut > elif Opcode==97: #dis.opmap[''STORE_GLOBAL']: 97, > IO_we.next=True > IO_addr.next=Arg1 > elif Opcode==114: #dis.opmap['POP_JUMP_IF_FALSE']: #: 114, > StackOP.next=STACK_POP > if StackValue0==0: > JumpValue.next=Arg1 > EnableJump.next=True > elif Opcode==115: #dis.opmap['POP_JUMP_IF_TRUE']: #: 115, > StackOP.next=STACK_POP > if StackValue0==1: > JumpValue.next=Arg1 > 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, > StackOP.next=STACK_ROT_THREE > 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 > 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?? > StackOP.next=STACK_NOP > else: > StackOP.next=STACK_NOP > #raise ValueError("Unsuported Command:"+str(Opcode)) > print "Comand not supported:",Opcode > > return > seq_logic,comb_logic,VariablesRAM_inst,ProgrammCode_inst,ConstantsROM_inst,TheStack_inst,IOModule_inst > > > 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) > > > def Processor_TESTBENCH(): > rst, clk = [Signal(bool(0)) for i in range(2)] > PORTA_IN=Signal(intbv(0)[32:]) > PORTB_IN=Signal(intbv(0)[32:]) > PORTC_OUT=Signal(intbv(0)[32:]) > PORTD_OUT=Signal(intbv(0)[32:]) > > toVHDL(Processor,clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT) > Processor_inst=Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT) > > > > @always(delay(10)) > def clkgen(): > clk.next = not clk > > @instance > def stimulus(): > print "#"*10+"Reseting"+"#"*10 > rst.next=0 > print "#"*10+"Setting PORTA_IN too 0"+"#"*10 > PORTA_IN.next=0 > > for i in range(3): > yield clk.negedge > print "#"*10+"Release Reset"+"#"*10 > rst.next=1 > > for i in range(200): > yield clk.negedge > > print "#"*10+"Setting PORTA_IN too 1"+"#"*10 > PORTA_IN.next=1 > for i in range(200): > yield clk.negedge > > PORTA_IN.next=0 > for i in range(500): > yield clk.negedge > > raise StopSimulation > > @instance > def Monitor_PORTC(): > print "\t\tPortC:",PORTC_OUT > while 1: > yield PORTC_OUT > print "\t\tPortC:",PORTC_OUT > > @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 > > #tb = traceSignals(Processor_TESTBENCH) > sim = Simulation(Processor_TESTBENCH()) > sim.run() > > #convert() > > #def simulate(timesteps): > # tb = traceSignals(test_dffa) > # sim = Simulation(tb) > # sim.run(timesteps) > > #simulate(20000) > > > ------------------------------------------------------------------------------ > Try before you buy = See our experts in action! > The most comprehensive online learning library for Microsoft developers > is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, > Metro Style Apps, more. Free future releases when you subscribe now! > http://p.sf.net/sfu/learndevnow-dev2 |
From: Christopher L. <loz...@fr...> - 2012-02-04 21:01:40
|
# # Description: Python Hardware Processor # This Code implements a Hardware CPU in myhdl. The code for the cpu is directly written in python # and since the hardware description is also in python, the programm code is automatically into the design # I love it. People like the author make me happy to have subscribed to this mailing list for the last year. Actually I had a vague idea like this in the back of my mind, but to actually see it in code is awesome. Makes it so much more concrete. Sir, I am sure that you have a lot of work to do, but if you go do a graphical image of the hardware architecture and data flow that would help me enormously to understand it. Trying to understand the code is hard work. How fast is this device compared to a traditional CPU? And then here is the million dollar question. How would you change the python language to better fit an FPGA? |
From: Norbo <Nor...@gm...> - 2012-02-04 13:49:12
|
To show where i am at: ##################################### # File: Core.py # Author: Norbert Feurle # Date: 4.2.2012 # # Description: Python Hardware Processor # This Code implements a Hardware CPU in myhdl. The code for the cpu is directly written in python # and since the hardware description is also in python, the programmcode is automatically into the design # The cool thing is that by this approach only memory and stack hardware is allocated in Hardware which is # really needed. Simulation of the code on the cpu running is no problem. (only python needed!) # The bytecode of python is executed at the cpu at one instruction per cycle # By now only simple bytecode instructions are supported # You can simply instantiate more Hardware CPUs on an FPGA with different program code to make it run parallel # # License: Pro life licence. # You are not allowed to 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 beings at an unacceptable rate, or build hardware # with it where te 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 ################################################################################################# ######################################################################################## #### Limitations: #### no lists, no dicts no tuples, no float, no complex numbers, #### no classmembers,no function calls, no multiplication, no exeptions, no for x in xxx:, etc. ######################################################################################## ### What is supported: ### ints(with x bits), no other python types ### simple if and while and assignments ### Operators: +, ^ , |, &. - (minus doesent work yet becaus i never used signed (big TODO)) ### Simple Digital IO with PORTs ### And of corse some bugs ######################################################################################## ##### The main programm for the python hardware porcessor to execute #### def CPU_main(): ## Reserves for IO Module ### global PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT PORTA_IN=0 #needs to bee here to reserve the right addresses (0 is written to nowhere) PORTB_IN=0 PORTC_OUT=0 PORTD_OUT=0 ################# x=0 while 1: x=x+1 if PORTA_IN==1: PORTC_OUT= PORTC_OUT^1 if x<20: PORTD_OUT=x elif x>=20 and x<25: PORTD_OUT=2**30+x else: PORTD_OUT=x ##### End of the main programm #### from myhdl import * import math import dis HAVE_ARGUMENT=dis.HAVE_ARGUMENT GLOBAL_PROGRAM=tuple([ord(i) for i in CPU_main.func_code.co_code]) + (0,0,) #because arguments are also read GLOBAL_CONSTANTS=(0,)+CPU_main.func_code.co_consts[1:] # because constant None is on address 0 but cpu only supports int GLOBAL_STACK_SIZE=CPU_main.func_code.co_stacksize GLOBAL_NUMBERSTACK_OPS=19 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,STACK_DUP_TOP=range(GLOBAL_NUMBERSTACK_OPS) def RAM(dout, din, addr, we, clk, WORD_SZ=8, DEPTH=16384): """ """ mem = [Signal(intbv(0)[WORD_SZ:]) for i in range(DEPTH)] @always(clk.posedge) def write(): if we: mem[int(addr)].next = din @always_comb def read(): dout.next = mem[int(addr)] return write,read def ROM(dout,addr,CONTENT): @always_comb def rom_logic(): dout.next= CONTENT[int(addr)] return rom_logic def ProgrammROM(Opcode,Arg1,Arg2,addr,CONTENT): @always_comb def progrom_logic(): Opcode.next= CONTENT[int(addr)] Arg1.next= CONTENT[int(addr+1)] Arg2.next= CONTENT[int(addr+2)] return progrom_logic def Stack(clk,rst,TopData_Out,Data_In,StackOP,CMPmode,WORD_SZ=32,SIZE=GLOBAL_STACK_SIZE): Stack_mem = [Signal(intbv(0)[WORD_SZ:]) for i in range(SIZE)] Next_TSO_Data=Signal(intbv(0)[WORD_SZ:]) TOS_Data=Signal(intbv(0)[WORD_SZ:]) TOS1_Data=Signal(intbv(0)[WORD_SZ:]) TOS2_Data=Signal(intbv(0)[WORD_SZ:]) TOS_Data_RD=Signal(intbv(0)[WORD_SZ:]) TOS1_Data_RD=Signal(intbv(0)[WORD_SZ:]) TOS2_Data_RD=Signal(intbv(0)[WORD_SZ:]) TOS_pointer_next=Signal(intbv(0,min=0,max=SIZE)) TOS_pointer= Signal(intbv(0,min=0,max=SIZE)) TOS1_pointer= Signal(intbv(0,min=0,max=SIZE)) TOS2_pointer= Signal(intbv(0,min=0,max=SIZE)) #TOS3_pointer= Signal(intbv(0,min=0,max=SIZE)) enable_stackpointer_increase=Signal(bool(0)) enable_stackpointer_deacrease=Signal(bool(0)) @always(clk.posedge,rst.negedge) def seq_logic(): if rst == 0: TOS_pointer_next.next=0 TOS_pointer.next=0 TOS1_pointer.next=0 TOS2_pointer.next=0 #TOS3_pointer.next=0 for indexer in range(SIZE): Stack_mem[int(indexer)].next=0 else: if enable_stackpointer_increase: TOS_pointer_next.next=(TOS_pointer_next+1)% SIZE TOS_pointer.next=TOS_pointer_next TOS1_pointer.next=TOS_pointer TOS2_pointer.next=TOS1_pointer if enable_stackpointer_deacrease: if TOS2_pointer==0: TOS2_pointer.next=SIZE-1 else: TOS2_pointer.next=TOS2_pointer-1 TOS1_pointer.next=TOS2_pointer TOS_pointer.next=TOS1_pointer TOS_pointer_next.next=TOS_pointer #Stackpointer.next=Stackpointer_next #attention if stacksize is to smalll the lower one gets overwritten #so the ordering is important # TODO: stacksize==1 would not work Stack_mem[int(TOS2_pointer)].next=TOS2_Data Stack_mem[int(TOS1_pointer)].next=TOS1_Data Stack_mem[int(TOS_pointer)].next=TOS_Data Stack_mem[int(TOS_pointer_next)].next=Next_TSO_Data @always_comb def comb_logic(): Next_TSO_Data.next=Stack_mem[int(TOS_pointer_next)] TOS_Data.next=Stack_mem[int(TOS_pointer)] TOS1_Data.next=Stack_mem[int(TOS1_pointer)] TOS2_Data.next=Stack_mem[int(TOS2_pointer)] enable_stackpointer_increase.next=1 enable_stackpointer_deacrease.next=0 if StackOP==STACK_NOP: enable_stackpointer_increase.next=0 elif StackOP==STACK_ADD: Next_TSO_Data.next=TOS1_Data_RD+TOS_Data_RD elif StackOP==STACK_POSITIVE: #??? Next_TSO_Data.next=TOS_Data_RD elif StackOP==STACK_NOT: Next_TSO_Data.next=TOS_Data_RD elif StackOP==STACK_NEGATIVE: Next_TSO_Data.next=-TOS_Data_RD elif StackOP==STACK_INVERT: Next_TSO_Data.next=~TOS_Data_RD elif StackOP==STACK_RSHIFT: Next_TSO_Data.next=TOS1_Data_RD>>TOS_Data_RD elif StackOP==STACK_LSHIFT: Next_TSO_Data.next=TOS1_Data_RD<<TOS_Data_RD elif StackOP==STACK_AND: Next_TSO_Data.next=TOS1_Data_RD&TOS_Data_RD elif StackOP==STACK_SUB: Next_TSO_Data.next=TOS1_Data_RD-TOS_Data_RD elif StackOP==STACK_OR: Next_TSO_Data.next=TOS1_Data_RD|TOS_Data_RD elif StackOP==STACK_XOR: Next_TSO_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_LOAD: Next_TSO_Data.next=Data_In elif StackOP==STACK_ROT_TWO: enable_stackpointer_increase.next=0 TOS_Data.next=TOS1_Data_RD TOS1_Data.next=TOS_Data_RD elif StackOP==STACK_ROT_THREE: enable_stackpointer_increase.next=0 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: Next_TSO_Data.next=TOS_Data_RD elif StackOP==STACK_CMP: if CMPmode==0: #operator < if TOS1_Data_RD<TOS_Data_RD: Next_TSO_Data.next=1 else: Next_TSO_Data.next=0 if CMPmode==1: #operator <= if TOS1_Data_RD<=TOS_Data_RD: Next_TSO_Data.next=1 else: Next_TSO_Data.next=0 if CMPmode==2: #operator == if TOS1_Data_RD==TOS_Data_RD: Next_TSO_Data.next=1 else: Next_TSO_Data.next=0 if CMPmode==3: #operator != if TOS1_Data_RD!=TOS_Data_RD: Next_TSO_Data.next=1 else: Next_TSO_Data.next=0 if CMPmode==4: #operator > if TOS1_Data_RD>TOS_Data_RD: Next_TSO_Data.next=1 else: Next_TSO_Data.next=0 if CMPmode==5: #operator >= if TOS1_Data_RD>=TOS_Data_RD: Next_TSO_Data.next=1 else: Next_TSO_Data.next=0 else: enable_stackpointer_increase.next=0 @always_comb def comb_logic2(): TOS_Data_RD.next=Stack_mem[int(TOS_pointer)] TOS1_Data_RD.next=Stack_mem[int(TOS1_pointer)] TOS2_Data_RD.next=Stack_mem[int(TOS2_pointer)] TopData_Out.next=Stack_mem[int(TOS_pointer)] return seq_logic,comb_logic,comb_logic2 def IOModule(clk,rst,dout,din,addr,we,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,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:]) @always(clk.posedge,rst.negedge) def IO_write_sync(): if rst==0: INTERN_PORTC_OUT.next=0 INTERN_PORTD_OUT.next=0 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 elif addr==3: INTERN_PORTD_OUT.next=din @always_comb 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 if addr==1: dout.next = Sync_in2_PORTB if addr==2: dout.next = INTERN_PORTC_OUT if addr==3: dout.next = INTERN_PORTD_OUT return IO_write_sync,IO_read def Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT,CPU_PROGRAM=GLOBAL_PROGRAM,CPU_CONSTANTS=GLOBAL_CONSTANTS,VAR_BITWIDTH=32,VAR_DEPTH=20,STACK_SIZE=GLOBAL_STACK_SIZE): #### helping signals EnableJump=Signal(bool(0)) JumpValue=Signal(intbv(0)[8:]) #### Programm Memory Signals Opcode=Signal(intbv(0)[8:]) Arg1=Signal(intbv(0)[8:]) Arg2=Signal(intbv(0)[8:]) ProgramCounter=Signal(intbv(0,min=0,max=len(CPU_main.func_code.co_code))) #### Constants Memory Signals ConstantsData=Signal(intbv(0)[VAR_BITWIDTH:]) ConstantsAddr=Signal(intbv(0,min=0,max=len(CPU_CONSTANTS))) #### Programm Variables RAM Signals Varibles_DataOut=Signal(intbv(0)[VAR_BITWIDTH:]) Variables_DataIn=Signal(intbv(0)[VAR_BITWIDTH:]) VariablesAddr=Signal(intbv(0,min=0,max=VAR_DEPTH)) Variables_we=Signal(bool(0)) #### Stack Signals # STACK_SIZE Stack_DataIn=Signal(intbv(0)[VAR_BITWIDTH:]) StackValue0=Signal(intbv(0)[VAR_BITWIDTH:]) StackOP=Signal(intbv(0,min=0,max=GLOBAL_NUMBERSTACK_OPS)) StackOP_CMPmode=Signal(intbv(0,min=0,max=len(dis.cmp_op))) #### IO Module Signals IO_MODULE_STARTADDRESSES=4 #IO_MODULE_ADDRESBITS=int(math.log(IO_MODULE_STARTADDRESSES,2)+1)-1 IO_DataOut=Signal(intbv(0)[VAR_BITWIDTH:]) IO_DataIn=Signal(intbv(0)[VAR_BITWIDTH:]) IO_addr=Signal(intbv(0,min=0,max=IO_MODULE_STARTADDRESSES)) IO_we=Signal(bool(0)) ####Variables RAM instantiation VariablesRAM_inst=RAM(Varibles_DataOut, Variables_DataIn, VariablesAddr, Variables_we, clk, WORD_SZ=VAR_BITWIDTH, DEPTH=VAR_DEPTH) ###Programm Code Memory instantiation ProgrammCode_inst=ProgrammROM(Opcode,Arg1,Arg2,ProgramCounter,CPU_PROGRAM) ###Constants memory instantiation ConstantsROM_inst=ROM(ConstantsData,ConstantsAddr,CPU_CONSTANTS) ###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,WIDTH=VAR_BITWIDTH) @always(clk.posedge,rst.negedge) def seq_logic(): if rst == 0: ##### ProgramCounter Part ######## ProgramCounter.next = 0 ##### END ProgramCounter Part ######## else: ##### ProgramCounter Part ######## if EnableJump==True:#StackValue0==bool(1)#Opcode==dis.opmap['POP_JUMP_IF_FALSE'] or Opcode==dis.opmap['POP_JUMP_IF_TRUE'] ProgramCounter.next=JumpValue else: if Opcode >= HAVE_ARGUMENT: ProgramCounter.next = ProgramCounter+3 else: ProgramCounter.next = ProgramCounter+1 ##### END ProgramCounter Part ######## ##### Opcode handling############# @always_comb def comb_logic(): JumpValue.next=0 EnableJump.next=False 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 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 elif Opcode==110: #dis.opmap['JUMP_FORWARD']: #: 110, EnableJump.next=True JumpValue.next=ProgramCounter+3+Arg1 elif Opcode==111: #dis.opmap['JUMP_IF_FALSE_OR_POP']: #: 111, if StackValue0==0: EnableJump.next=True JumpValue.next=Arg1 elif Opcode==112: #dis.opmap['JUMP_IF_TRUE_OR_POP']: #: 112, if StackValue0==1: JumpValue.next=Arg1 EnableJump.next=True else: StackOP.next=STACK_POP elif Opcode==100: #dis.opmap['LOAD_CONST']: #: 100, StackOP.next=STACK_LOAD Stack_DataIn.next=ConstantsData ConstantsAddr.next=Arg1 elif Opcode==124: #dis.opmap['LOAD_FAST']: #: 124, StackOP.next=STACK_LOAD VariablesAddr.next=Arg1 Stack_DataIn.next=Varibles_DataOut elif Opcode==116: #dis.opmap['LOAD_GLOBAL']: 116, StackOP.next=STACK_LOAD IO_addr.next=Arg1 Stack_DataIn.next=IO_DataOut elif Opcode==97: #dis.opmap[''STORE_GLOBAL']: 97, IO_we.next=True IO_addr.next=Arg1 elif Opcode==114: #dis.opmap['POP_JUMP_IF_FALSE']: #: 114, StackOP.next=STACK_POP if StackValue0==0: JumpValue.next=Arg1 EnableJump.next=True elif Opcode==115: #dis.opmap['POP_JUMP_IF_TRUE']: #: 115, StackOP.next=STACK_POP if StackValue0==1: JumpValue.next=Arg1 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, StackOP.next=STACK_ROT_THREE 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 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?? StackOP.next=STACK_NOP else: StackOP.next=STACK_NOP #raise ValueError("Unsuported Command:"+str(Opcode)) print "Comand not supported:",Opcode return seq_logic,comb_logic,VariablesRAM_inst,ProgrammCode_inst,ConstantsROM_inst,TheStack_inst,IOModule_inst 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) def Processor_TESTBENCH(): rst, clk = [Signal(bool(0)) for i in range(2)] PORTA_IN=Signal(intbv(0)[32:]) PORTB_IN=Signal(intbv(0)[32:]) PORTC_OUT=Signal(intbv(0)[32:]) PORTD_OUT=Signal(intbv(0)[32:]) toVHDL(Processor,clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT) Processor_inst=Processor(clk,rst,PORTA_IN,PORTB_IN,PORTC_OUT,PORTD_OUT) @always(delay(10)) def clkgen(): clk.next = not clk @instance def stimulus(): print "#"*10+"Reseting"+"#"*10 rst.next=0 print "#"*10+"Setting PORTA_IN too 0"+"#"*10 PORTA_IN.next=0 for i in range(3): yield clk.negedge print "#"*10+"Release Reset"+"#"*10 rst.next=1 for i in range(200): yield clk.negedge print "#"*10+"Setting PORTA_IN too 1"+"#"*10 PORTA_IN.next=1 for i in range(200): yield clk.negedge PORTA_IN.next=0 for i in range(500): yield clk.negedge raise StopSimulation @instance def Monitor_PORTC(): print "\t\tPortC:",PORTC_OUT while 1: yield PORTC_OUT print "\t\tPortC:",PORTC_OUT @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 #tb = traceSignals(Processor_TESTBENCH) sim = Simulation(Processor_TESTBENCH()) sim.run() #convert() #def simulate(timesteps): # tb = traceSignals(test_dffa) # sim = Simulation(tb) # sim.run(timesteps) #simulate(20000) |
From: Christopher F. <chr...@gm...> - 2012-02-01 14:32:06
|
On 2/1/2012 6:41 AM, Tim Brooks wrote: >>> Python also has sockets but I can't imaging it would be easy to tell it >>> to send and receive packet to the myhdl test bench would it?... >> >> Well that's the point of MyHDL - it is easy. Just mix the socket >> functions with the rest of the testbench code. >> > really? I wouldn't say easy - from googling around it, I think it would > involve creating a pseudo Ethernet device and binding the socket to > that device. The testbench would read and write Ethernet frames from/to > that device. a little beyond my python/unix skills at the moment. >> For co-simulation, I don't think there's support for any VHDL simulator >> today (not even GHDL), is there? "Easy" is Sebastien's brash way of saying straight-forward. It might take some coding to create the _transactor_ that receives the packets over a socket and convert them to a bus driver (e.g. MII, GMII) but there should be no limitation in doing so. If you were able to create a Python module that listened for a socket connection and could connect externally. At that point you could translate the received packet information into the bus transactor. You might have to add some of the lower-level TCP/IP wrappers depending what level you are testing. > > Shame... As far as VHDL cosimulation simulator support it is nil. iSIM does not have PLI/VPI/VHPI/DPI support. It will not be possible to use iSIM for cosimulation. GHDLs VHPI support is limited and in an unknown state. There have been some experiments ... http://www.myhdl.org/doku.php/dev:vhdl_cosim In the past there has been, either limited access to a VHDL simulator with mature VHPI support to develop VHDL cosimulation or little interest. If you want to start an initiative to investigate or build the VHPI interface to a simulator with mature/stable VHPI I will be happy to assist. Otherwise, I don't believe there is anyone with cycles to complete cosimulation with a VHDL simulator. Best of my knowledge Modelsim and Active-HDL both have decent VHPI support. I believe the free Modelsim with the Altera tools could be used to develop the VHDL-VHPI interface. Regards, Chris |
From: Sébastien B. <seb...@mi...> - 2012-02-01 12:44:09
|
On 02/01/2012 01:41 PM, Tim Brooks wrote: >>> Python also has sockets but I can't imaging it would be easy to tell it >>> >> to send and receive packet to the myhdl test bench would it?... >> > >> > Well that's the point of MyHDL - it is easy. Just mix the socket >> > functions with the rest of the testbench code. >> > > really? I wouldn't say easy Well, that's certainly easier than using VPI/VHPI and C programming :) |
From: Tim B. <tim...@so...> - 2012-02-01 12:42:03
|
>> Python also has sockets but I can't imaging it would be easy to tell it >> to send and receive packet to the myhdl test bench would it?... > > Well that's the point of MyHDL - it is easy. Just mix the socket > functions with the rest of the testbench code. > really? I wouldn't say easy - from googling around it, I think it would involve creating a pseudo Ethernet device and binding the socket to that device. The testbench would read and write Ethernet frames from/to that device. a little beyond my python/unix skills at the moment. > For co-simulation, I don't think there's support for any VHDL simulator > today (not even GHDL), is there? Shame... |
From: Sébastien B. <seb...@mi...> - 2012-02-01 10:12:45
|
On 02/01/2012 10:06 AM, Tim Brooks wrote: > Python also has sockets but I can't imaging it would be easy to tell it > to send and receive packet to the myhdl test bench would it?... Well that's the point of MyHDL - it is easy. Just mix the socket functions with the rest of the testbench code. For co-simulation, I don't think there's support for any VHDL simulator today (not even GHDL), is there? Sébastien |
From: Tim B. <tim...@so...> - 2012-02-01 10:09:29
|
Hi, I've been writing VHDL for Xilinx FPGAs for a few year now. I use the standard Xilinx tool including ISIM for simulation. I've also picked up a bit of python along the way. Then I found MyHDL. I really like the idea and have installed it and gone through some of the examples. The project I'm currently working is basically a Gigabit Ethernet TCP socket to connect to a High speed serial IO. Any data that comes across the TCP/IP socket gets sent to the serial IO and vice versa. Python has dpkt, so I can craft Ethernet, ip, arp, tcp... packets very easily. However, it would still involve a little work to craft frames dynamically. Much easier than the alternative of doing it in VHDL! For now I'm making frames with dpkt and saving them to a file and reading the file into a VHDL testbench. Python also has sockets but I can't imaging it would be easy to tell it to send and receive packet to the myhdl test bench would it?... Now I have read that there is not much support for vhdl co simulation, and in fact, none for ISIM: it doesn;t have a VHPI interface. However, I would be willing to try GHDL if the community thinks it is mature enough to have a go with for this application. What do you think? Tim -- Senior Design Engineer Somerdata Ltd 1 Riverside Business Park St Annes Road Bristol BS4 4ED Tel: +44 (0)117 9634050 Fax: +44 (0)117 3302929 E-mail: tim...@so... Website: www.somerdata.com |
From: Wesley N. <we...@sk...> - 2012-01-24 11:54:45
|
Thank you for the replies. To update on this issue I have confirmed that the method Chris suggested works. ie creating a function outside the class and passing that to the convert method. I am not comfortable with doing it this way as it is a bit of a hack, but until we can patch MyHDL it will have to do. Regards Wesley On Thu, Jan 19, 2012 at 3:35 PM, Sébastien Bourdeauducq < seb...@mi...> wrote: > On 01/19/2012 01:23 PM, Christopher Felton wrote: > > This is currently a known limitation, you cannot convert a class method > > directly because the convert does not recognize the first parameter, > > "self", and uses "self" as a port. > > If your design is synchronous, and if using classes is more important to > you than integrated Python test benches (which are perfectly possible to > do under Migen, but which no one has developed yet) you can use Migen > FHDL, which supports signals in classes (and more perversions) just fine. > > https://github.com/milkymist/migen > > Sébastien > > > ------------------------------------------------------------------------------ > Keep Your Developer Skills Current with LearnDevNow! > The most comprehensive online learning library for Microsoft developers > is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, > Metro Style Apps, more. Free future releases when you subscribe now! > http://p.sf.net/sfu/learndevnow-d2d > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > |
From: Sébastien B. <seb...@mi...> - 2012-01-19 13:40:43
|
On 01/19/2012 01:23 PM, Christopher Felton wrote: > This is currently a known limitation, you cannot convert a class method > directly because the convert does not recognize the first parameter, > "self", and uses "self" as a port. If your design is synchronous, and if using classes is more important to you than integrated Python test benches (which are perfectly possible to do under Migen, but which no one has developed yet) you can use Migen FHDL, which supports signals in classes (and more perversions) just fine. https://github.com/milkymist/migen Sébastien |
From: Christopher F. <chr...@gm...> - 2012-01-19 12:24:31
|
On 1/19/12 5:51 AM, Wesley New wrote: > Hi All, > > I have had to change the way my uesr-defined code was written to the new > method, using <func>.verilog_code but I am having a problem using it > inside a class. > > Here is the code: > > from myhdl import * > > class sw_reg: > > def __init__(self): > #self.sw_reg_r_wrapper.__dict__['verilog_code'] = "verilog" > #self.sw_reg_r_wrapper.verilog_code = "verilog" > temp2 = 0 > > > def sw_reg_wrapper(self, wb_clk_i): > > #======================== > # TODO:Simulation Logic > #======================== > @always(wb_clk_i.posedge) > def logic(): > temp = 1 > > return logic > > sw_reg_r_wrapper.verilog_code = "verilog code blah blah" > > > But when I call the toVerilog method, as below, it doesnt use the > user-defined code (Note: this works when there is no class) > > #======================================= > # For testing of conversion to verilog > #======================================= > def convert(): > > x = sw_reg_r() > wb_clk_i = Signal(bool(0)) > > toVerilog(x.sw_reg_r_wrapper, wb_clk_i=wb_clk_i) > > > if __name__ == "__main__": > convert() > > I have tried adding the verilog_code explicitly to the dictionary > associated with the function (See the commented lines in the __init__ > function) but this doesnt work either. What am I doing wrong? > > Thanks for you time. > > Wesley > > > This is currently a known limitation, you cannot convert a class method directly because the convert does not recognize the first parameter, "self", and uses "self" as a port. The current work around, is to have a normal function that is converted and have the class method invoke the function (essentially pass all arguments except self). This is one of the items I was hoping to address in the MEP I proposed but finding adequate time to work on it is, lets say, difficult. Hope that helps, Chris |
From: Wesley N. <we...@sk...> - 2012-01-19 11:51:52
|
Hi All, I have had to change the way my uesr-defined code was written to the new method, using <func>.verilog_code but I am having a problem using it inside a class. Here is the code: from myhdl import * class sw_reg: def __init__(self): #self.sw_reg_r_wrapper.__dict__['verilog_code'] = "verilog" #self.sw_reg_r_wrapper.verilog_code = "verilog" temp2 = 0 def sw_reg_wrapper(self, wb_clk_i): #======================== # TODO:Simulation Logic #======================== @always(wb_clk_i.posedge) def logic(): temp = 1 return logic sw_reg_r_wrapper.verilog_code = "verilog code blah blah" But when I call the toVerilog method, as below, it doesnt use the user-defined code (Note: this works when there is no class) #======================================= # For testing of conversion to verilog #======================================= def convert(): x = sw_reg_r() wb_clk_i = Signal(bool(0)) toVerilog(x.sw_reg_r_wrapper, wb_clk_i=wb_clk_i) if __name__ == "__main__": convert() I have tried adding the verilog_code explicitly to the dictionary associated with the function (See the commented lines in the __init__ function) but this doesnt work either. What am I doing wrong? Thanks for you time. Wesley |
From: Christopher F. <chr...@gm...> - 2012-01-19 10:15:31
|
On 1/18/12 6:35 AM, Matti wrote: > I want to do something like this: > > def myfunc(data): > return float(data) > > def Int2Float(inval, outval, clock): > @always(clock.posedge) > def Int2FloatLogic(): > out.next = myfunc(data) > return instances > > Of course this will not pass the convertor. But I would like to use it in > simulation, and at a later date replace the float() call with an appropriate > vendor-supplied library. In the real example myfunc is more complicated. > Questions: > - How can I get the simulator to just execute the python code without trying to > convert it to myhdl primitives? > - How do I tell the simulator that myfunc requires 28 clock cycles? > > Thanks, > Matti > As you elude, you can use any valid Python in simulation (this is why any other HDL language is extinct for verification!). In Python speak you want to create a generator that can be passed to the MyHDL simulation engine. Your example would be valid other than it does not have the 28 clock cycle delay. You could add a counter to count clock cycles or you could use the delay (@always(delay(28*CLK_SIM_STEPS))). By using the delay in the @always decorator your generator will only execute the specified number of simulation steps. Another, slightly more flexible, way to write generators is like the following. def mod(): @instance def tb_model(): # Init variables while(True): out.next = myfunc(data) yield delay(28*CLK_SIM_STEPS) # can do some more # ... In the above form, you have a little more flexibility but you have to be more explicit. It doesn't "feel" as hardware description as the decorators (@always, @always_comb). In the above you can use the delay or you can use a "variable" as a counter. Hope that helps, Chris |
From: Matti <mat...@gm...> - 2012-01-18 12:40:26
|
I want to do something like this: def myfunc(data): return float(data) def Int2Float(inval, outval, clock): @always(clock.posedge) def Int2FloatLogic(): out.next = myfunc(data) return instances Of course this will not pass the convertor. But I would like to use it in simulation, and at a later date replace the float() call with an appropriate vendor-supplied library. In the real example myfunc is more complicated. Questions: - How can I get the simulator to just execute the python code without trying to convert it to myhdl primitives? - How do I tell the simulator that myfunc requires 28 clock cycles? Thanks, Matti |
From: Wesley N. <we...@sk...> - 2012-01-12 14:01:59
|
Wonderful, Thanks for the help Chris. On Thu, Jan 12, 2012 at 3:51 PM, Christopher Felton <chr...@gm...>wrote: > On 1/12/2012 6:06 AM, Wesley New wrote: > > I have been creating the toplevel of my design and while converting to > > verilog and have come across a problem similar to the one discussed here: > > > > http://comments.gmane.org/gmane.comp.python.myhdl/1568 > > > > to quote Jan: > > > > "The problem is that Verilog doesn't permit memories as ports. > > As my goal is to support both Verilog and VHDL equally, I have > > to use the lowest common demoninator. Therefore, list of signals > > as ports are not supported." > > > > I have been able to create and synthesize lists of ports in verilog at > the > > toplevel without problems, but MyHDL doesnt support this. Is this to do > > with the version of verilog or am I missing something? > > > > So for instance: > > > > module toplevel ( > > > > .. > > * output* [ 7:0] gpio > > ... > > ); > > > > This is used along with a UCT file with the following lines: > > > > NET "gpio<0>" LOC = G31 | IOSTANDARD = "LVCMOS15"; NET "gpio<1>" LOC = > H31 > > | IOSTANDARD = "LVCMOS15"; NET "gpio<2>" LOC = AF32 | IOSTANDARD = > > "LVCMOS15"; NET "gpio<3>" LOC = AG33 | IOSTANDARD = "LVCMOS15"; NET > > "gpio<4>" LOC = L30 | IOSTANDARD = "LVCMOS15"; NET "gpio<5>" LOC = H30 | > > IOSTANDARD = "LVCMOS15"; NET "gpio<6>" LOC = M29 | IOSTANDARD = > "LVCMOS15"; > > NET "gpio<7>" LOC = J30 | IOSTANDARD = "LVCMOS15"; > > > > And this works with out hassles. But when I use MyHDL... > > > > My MyHDL toplevel looks like this: > > > > from myhdl import * > > > > def toplevel( > > sys_clk_n, > > sys_clk_p, > > gpio, > > ): > > > > > > def convert(): > > sys_clk_n, sys_clk_p = [Signal(bool(0)) for i in range(2)] > > # MyHDL doesnt support passing a list of ports > > # this is just silently dropped! > > gpio = [Signal(intbv(0)[15:]] > > You don't need to do this, have gpio be a list, just simply use > > gpio = Signal(intbv(0)[15:]) > > That should fix the issue. Note: a list of signals is not support as > ports. > > Hope that helps, > Chris > > > > > toVerilog(roach2_base, sys_clk_n, sys_clk_p, gpio) > > > > I get and ERROR: List of signals as a port is not supported: gpio > > > > I know verilog doesnt support passing of 2D arrays as ports, but I have > > definitely used a list of ports (Single dimension array) at the toplevel. > > > > Can some help me shed some light on this issue? Am I doing something > wrong? > > > > > > Regards > > > > Wes > > > > > > > > > > > ------------------------------------------------------------------------------ > > RSA(R) Conference 2012 > > Mar 27 - Feb 2 > > Save $400 by Jan. 27 > > Register now! > > http://p.sf.net/sfu/rsa-sfdev2dev2 > > > > > > > > _______________________________________________ > > myhdl-list mailing list > > myh...@li... > > https://lists.sourceforge.net/lists/listinfo/myhdl-list > > > > > ------------------------------------------------------------------------------ > RSA(R) Conference 2012 > Mar 27 - Feb 2 > Save $400 by Jan. 27 > Register now! > http://p.sf.net/sfu/rsa-sfdev2dev2 > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > |
From: Christopher F. <chr...@gm...> - 2012-01-12 13:52:01
|
On 1/12/2012 6:06 AM, Wesley New wrote: > I have been creating the toplevel of my design and while converting to > verilog and have come across a problem similar to the one discussed here: > > http://comments.gmane.org/gmane.comp.python.myhdl/1568 > > to quote Jan: > > "The problem is that Verilog doesn't permit memories as ports. > As my goal is to support both Verilog and VHDL equally, I have > to use the lowest common demoninator. Therefore, list of signals > as ports are not supported." > > I have been able to create and synthesize lists of ports in verilog at the > toplevel without problems, but MyHDL doesnt support this. Is this to do > with the version of verilog or am I missing something? > > So for instance: > > module toplevel ( > > .. > * output* [ 7:0] gpio > ... > ); > > This is used along with a UCT file with the following lines: > > NET "gpio<0>" LOC = G31 | IOSTANDARD = "LVCMOS15"; NET "gpio<1>" LOC = H31 > | IOSTANDARD = "LVCMOS15"; NET "gpio<2>" LOC = AF32 | IOSTANDARD = > "LVCMOS15"; NET "gpio<3>" LOC = AG33 | IOSTANDARD = "LVCMOS15"; NET > "gpio<4>" LOC = L30 | IOSTANDARD = "LVCMOS15"; NET "gpio<5>" LOC = H30 | > IOSTANDARD = "LVCMOS15"; NET "gpio<6>" LOC = M29 | IOSTANDARD = "LVCMOS15"; > NET "gpio<7>" LOC = J30 | IOSTANDARD = "LVCMOS15"; > > And this works with out hassles. But when I use MyHDL... > > My MyHDL toplevel looks like this: > > from myhdl import * > > def toplevel( > sys_clk_n, > sys_clk_p, > gpio, > ): > > > def convert(): > sys_clk_n, sys_clk_p = [Signal(bool(0)) for i in range(2)] > # MyHDL doesnt support passing a list of ports > # this is just silently dropped! > gpio = [Signal(intbv(0)[15:]] You don't need to do this, have gpio be a list, just simply use gpio = Signal(intbv(0)[15:]) That should fix the issue. Note: a list of signals is not support as ports. Hope that helps, Chris > > toVerilog(roach2_base, sys_clk_n, sys_clk_p, gpio) > > I get and ERROR: List of signals as a port is not supported: gpio > > I know verilog doesnt support passing of 2D arrays as ports, but I have > definitely used a list of ports (Single dimension array) at the toplevel. > > Can some help me shed some light on this issue? Am I doing something wrong? > > > Regards > > Wes > > > > > ------------------------------------------------------------------------------ > RSA(R) Conference 2012 > Mar 27 - Feb 2 > Save $400 by Jan. 27 > Register now! > http://p.sf.net/sfu/rsa-sfdev2dev2 > > > > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list |
From: Wesley N. <we...@sk...> - 2012-01-12 12:31:15
|
I have been creating the toplevel of my design and while converting to verilog and have come across a problem similar to the one discussed here: http://comments.gmane.org/gmane.comp.python.myhdl/1568 to quote Jan: "The problem is that Verilog doesn't permit memories as ports. As my goal is to support both Verilog and VHDL equally, I have to use the lowest common demoninator. Therefore, list of signals as ports are not supported." I have been able to create and synthesize lists of ports in verilog at the toplevel without problems, but MyHDL doesnt support this. Is this to do with the version of verilog or am I missing something? So for instance: module toplevel ( .. * output* [ 7:0] gpio .. ); This is used along with a UCT file with the following lines: NET "gpio<0>" LOC = G31 | IOSTANDARD = "LVCMOS15"; NET "gpio<1>" LOC = H31 | IOSTANDARD = "LVCMOS15"; NET "gpio<2>" LOC = AF32 | IOSTANDARD = "LVCMOS15"; NET "gpio<3>" LOC = AG33 | IOSTANDARD = "LVCMOS15"; NET "gpio<4>" LOC = L30 | IOSTANDARD = "LVCMOS15"; NET "gpio<5>" LOC = H30 | IOSTANDARD = "LVCMOS15"; NET "gpio<6>" LOC = M29 | IOSTANDARD = "LVCMOS15"; NET "gpio<7>" LOC = J30 | IOSTANDARD = "LVCMOS15"; And this works with out hassles. But when I use MyHDL... My MyHDL toplevel looks like this: from myhdl import * def toplevel( sys_clk_n, sys_clk_p, gpio, ): def convert(): sys_clk_n, sys_clk_p = [Signal(bool(0)) for i in range(2)] # MyHDL doesnt support passing a list of ports # this is just silently dropped! gpio = [Signal(intbv(0)[15:]] toVerilog(roach2_base, sys_clk_n, sys_clk_p, gpio) I get and ERROR: List of signals as a port is not supported: gpio I know verilog doesnt support passing of 2D arrays as ports, but I have definitely used a list of ports (Single dimension array) at the toplevel. Can some help me shed some light on this issue? Am I doing something wrong? Regards Wes |
From: Christopher F. <chr...@gm...> - 2011-12-27 13:20:54
|
On 12/23/2011 8:48 AM, Christopher Felton wrote: > On Tuesday, December 20, 2011, Oscar Diaz<osc...@gm...> wrote: >> 2011/12/20 Christopher Felton<chr...@gm...>: >>> On 12/20/2011 5:35 AM, Oscar Diaz wrote: >>>> Hi >>>> >>>> I have a testbench that needs to do some asserts at the end of a >>>> simulation. However, I couldn't find an elegant way to do it. Right >>>> now I'm passing to the testbench generator the same duration as in >>>> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" >>>> and do the final asserts (by the way, in my case all my simulations >>>> have a defined duration). I tried to catch the StopSimulation >>>> exception, but it doesn't work inside a generator. Any ideas? Thanks! >>>> >>>> Best regards >>>> >>> >>> I believe you can catch exceptions in generators. At least the >>> generator PEP says so and the following works. >>> >>> ~~~ [Code Snip] ~~~ >>> from myhdl import * >>> def test(): >>> @instance >>> def ex_in_g(): >>> try: >>> for ii in xrange(10): >>> yield delay(7) >>> raise StopSimulation >>> >>> except Exception, e: >>> print("Caught exception %s" % (str(e))) >>> raise StopSimulation >>> >>> return ex_in_g >>> >>> if __name__ == '__main__': >>> Simulation(test()).run() >>> ~~~~~~~~~~~~~~~~~~~~~~~ >> >> That's the case when the exception is raised inside the generator, >> which is not my case. I'm trying to something like this: >> >> ~~~ [Code Snip] ~~~ >> from myhdl import * >> def test(): >> @instance >> def ex_in_g(): >> try: >> for ii in xrange(10): >> yield delay(7) >> # ideally it shouldn't got here >> return >> >> except Exception, e: >> # or maybe better "except StopSimulation" ? >> print("Caught exception %s" % (str(e))) >> raise StopSimulation >> >> return ex_in_g >> >> if __name__ == '__main__': >> # fixed simulation time >> Simulation(test()).run(50) >> ~~~~~~~~~~~~~~~~~~~~~~~ >> >> It doesn't work because the exception is raised inside the run() >> method. Right now my project store the simulation duration to yield >> before raising StopSimulation, like this: >> ~~~ [Code Snip] ~~~ >> from myhdl import * >> sim_duration = 100 >> def test(): >> @instance >> def main_block(): >> # do some stuff >> return >> >> @instance >> def last_check(): >> yield delay(sim_duration - 1) >> print "do some final asserts..." >> return >> >> return instances() >> >> if __name__ == '__main__': >> Simulation(test()).run(sim_duration) >> ~~~~~~~~~~~~~~~~~~~~~~~ >> >> Any ideas to improve this issue? >> >> Best regards >> >>> >>> Regards, >>> Chris >>> >>> > > Another option you could try is to run the simulation from the test > function. After the simulation completes the final state is preserved and > you can do the final checks. > > I haven't tried it. In the above example, the test function you could do > the following. > > Def test(): > ... > Simulation((ex_in_g)).run() > #checks > # nothing to return > > Regards, > Chris > > > > Here is a complete example that I briefly mentioned previously. The following, there is a simple module that will stop counting at some value. The simulation is run for some period of steps and the state is maintained for variables/objects that are active (? don't know the correct programming lingo for variables/objects that are in scope and have not been discarded). ~~~[Code Snip]~~~ from myhdl import * def incr(clk, rst, x): @always(clk.posedge) def hdlg_incr(): if rst: x.next = 0 else: if x < 12: x.next = x + 1 return hdlg_incr def test(): clk = Signal(False) rst = Signal(False) x = Signal(intbv(0, min=0, max=20)) dut = incr(clk, rst, x) @always(delay(1)) def tb_clk_gen(): clk.next = not clk @instance def tb_stim(): rst.next = True yield delay(3) rst.next = False # Run the simulation Simulation((dut, tb_clk_gen, tb_stim)).run(44) # Check final state assert x == 12, "Final state incorrect" assert x != 12, "Final state correct" if __name__ == '__main__': test() ~~~[End Code Snip]~~~ ~~~[CLI exec]~~~ In [2]: run end_state.py <class 'myhdl._SuspendSimulation'>: Simulated 44 timesteps --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) end_state.py in <module>() 40 41 if __name__ == '__main__': ---> 42 test() 43 \\sppdgfs\users\felton\misc\test\end_state.py in test() 36 37 assert x == 12, "Final state incorrect" ---> 38 assert x != 12, "Final state correct" 39 40 AssertionError: Final state correct ~~~[End CLI exec]~~~ Now, I don't think you can dig down and check internal variables this way (at least I do not know how to). Regards, Chris |
From: Uri N. <ur...@gm...> - 2011-12-26 19:32:35
|
On 23 December 2011 16:48, Christopher Felton <chr...@gm...>wrote: > > > On Tuesday, December 20, 2011, Oscar Diaz <osc...@gm...> wrote: > > 2011/12/20 Christopher Felton <chr...@gm...>: > >> On 12/20/2011 5:35 AM, Oscar Diaz wrote: > >>> Hi > >>> > >>> I have a testbench that needs to do some asserts at the end of a > >>> simulation. However, I couldn't find an elegant way to do it. Right > >>> now I'm passing to the testbench generator the same duration as in > >>> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" > >>> and do the final asserts (by the way, in my case all my simulations > >>> have a defined duration). I tried to catch the StopSimulation > >>> exception, but it doesn't work inside a generator. Any ideas? Thanks! > >>> > >>> Best regards > >>> > >> > >> I believe you can catch exceptions in generators. At least the > >> generator PEP says so and the following works. > >> > >> ~~~ [Code Snip] ~~~ > >> from myhdl import * > >> def test(): > >> @instance > >> def ex_in_g(): > >> try: > >> for ii in xrange(10): > >> yield delay(7) > >> raise StopSimulation > >> > >> except Exception, e: > >> print("Caught exception %s" % (str(e))) > >> raise StopSimulation > >> > >> return ex_in_g > >> > >> if __name__ == '__main__': > >> Simulation(test()).run() > >> ~~~~~~~~~~~~~~~~~~~~~~~ > > > > That's the case when the exception is raised inside the generator, > > which is not my case. I'm trying to something like this: > > > > ~~~ [Code Snip] ~~~ > > from myhdl import * > > def test(): > > @instance > > def ex_in_g(): > > try: > > for ii in xrange(10): > > yield delay(7) > > # ideally it shouldn't got here > > return > > > > except Exception, e: > > # or maybe better "except StopSimulation" ? > > print("Caught exception %s" % (str(e))) > > raise StopSimulation > > > > return ex_in_g > > > > if __name__ == '__main__': > > # fixed simulation time > > Simulation(test()).run(50) > > ~~~~~~~~~~~~~~~~~~~~~~~ > > > > It doesn't work because the exception is raised inside the run() > > method. Right now my project store the simulation duration to yield > > before raising StopSimulation, like this: > > ~~~ [Code Snip] ~~~ > > from myhdl import * > > sim_duration = 100 > > def test(): > > @instance > > def main_block(): > > # do some stuff > > return > > > > @instance > > def last_check(): > > yield delay(sim_duration - 1) > > print "do some final asserts..." > > return > > > > return instances() > > > > if __name__ == '__main__': > > Simulation(test()).run(sim_duration) > > ~~~~~~~~~~~~~~~~~~~~~~~ > > > > Any ideas to improve this issue? > > > > Best regards > > > >> > >> Regards, > >> Chris > >> > >> > > Another option you could try is to run the simulation from the test > function. After the simulation completes the final state is preserved and > you can do the final checks. > > I haven't tried it. In the above example, the test function you could do > the following. > > Def test(): > ... > Simulation((ex_in_g)).run() > #checks > # nothing to return > > Regards, > Chris > > ------------------------------------------------------------------------------ > Write once. Port to many. > Get the SDK and tools to simplify cross-platform app development. Create > new or port existing apps to sell to consumers worldwide. Explore the > Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join > http://p.sf.net/sfu/intel-appdev > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > > Hi, Perhaps something like the following is suitable: the stimulus generator halts the simulation once the vector is exhausted. No need to catch anything. I did need to use an object to store the result, since the Signals go dead at the end of the simulation. Cheers, Uri ~~~ [Code Snip] ~~~ #! /usr/bin/python import unittest import myhdl from myhdl import Signal, always, instance, delay def Clock(clk): @always(delay(1)) def logic(): clk.next ^= 1 return logic def DUT(clk, din, dout): @always(clk.posedge) def logic(): dout.next = din.val + 1 return logic class Monitor(): def __init__(self): self.sample = 0 def update(self, clk, din): @always(clk.posedge) def logic(): self.sample = din.val return logic class TestDUT(unittest.TestCase): # unittest methods def setUp(self): self.clk = Signal(0) self.din = Signal(0) self.dout = Signal(0) self.clk_inst = Clock(self.clk) self.dut_inst = DUT(self.clk, self.din, self.dout) self.monitor = Monitor() self.monitor_inst = self.monitor.update(self.clk, self.dout) def tearDown(self): pass # specific test methods (scenarios) def test_3(self): def stimulus(stimVector): @instance def logic(): for data in stimVector: self.din.next = data yield self.clk.posedge raise myhdl.StopSimulation return logic stimulus_inst = stimulus(range(1,7)) sim = myhdl.Simulation(self.dut_inst, self.clk_inst, self.monitor_inst, stimulus_inst) sim.run() self.assert_(self.monitor.sample == 5) if __name__ == '__main__': mytests = unittest.TestLoader().loadTestsFromTestCase(TestDUT) unittest.TextTestRunner(verbosity=2).run(mytests) |
From: Christopher F. <chr...@gm...> - 2011-12-23 14:49:02
|
On Tuesday, December 20, 2011, Oscar Diaz <osc...@gm...> wrote: > 2011/12/20 Christopher Felton <chr...@gm...>: >> On 12/20/2011 5:35 AM, Oscar Diaz wrote: >>> Hi >>> >>> I have a testbench that needs to do some asserts at the end of a >>> simulation. However, I couldn't find an elegant way to do it. Right >>> now I'm passing to the testbench generator the same duration as in >>> "Simulation.run(duration)" , so I can do a "yield delay(duration-1)" >>> and do the final asserts (by the way, in my case all my simulations >>> have a defined duration). I tried to catch the StopSimulation >>> exception, but it doesn't work inside a generator. Any ideas? Thanks! >>> >>> Best regards >>> >> >> I believe you can catch exceptions in generators. At least the >> generator PEP says so and the following works. >> >> ~~~ [Code Snip] ~~~ >> from myhdl import * >> def test(): >> @instance >> def ex_in_g(): >> try: >> for ii in xrange(10): >> yield delay(7) >> raise StopSimulation >> >> except Exception, e: >> print("Caught exception %s" % (str(e))) >> raise StopSimulation >> >> return ex_in_g >> >> if __name__ == '__main__': >> Simulation(test()).run() >> ~~~~~~~~~~~~~~~~~~~~~~~ > > That's the case when the exception is raised inside the generator, > which is not my case. I'm trying to something like this: > > ~~~ [Code Snip] ~~~ > from myhdl import * > def test(): > @instance > def ex_in_g(): > try: > for ii in xrange(10): > yield delay(7) > # ideally it shouldn't got here > return > > except Exception, e: > # or maybe better "except StopSimulation" ? > print("Caught exception %s" % (str(e))) > raise StopSimulation > > return ex_in_g > > if __name__ == '__main__': > # fixed simulation time > Simulation(test()).run(50) > ~~~~~~~~~~~~~~~~~~~~~~~ > > It doesn't work because the exception is raised inside the run() > method. Right now my project store the simulation duration to yield > before raising StopSimulation, like this: > ~~~ [Code Snip] ~~~ > from myhdl import * > sim_duration = 100 > def test(): > @instance > def main_block(): > # do some stuff > return > > @instance > def last_check(): > yield delay(sim_duration - 1) > print "do some final asserts..." > return > > return instances() > > if __name__ == '__main__': > Simulation(test()).run(sim_duration) > ~~~~~~~~~~~~~~~~~~~~~~~ > > Any ideas to improve this issue? > > Best regards > >> >> Regards, >> Chris >> >> Another option you could try is to run the simulation from the test function. After the simulation completes the final state is preserved and you can do the final checks. I haven't tried it. In the above example, the test function you could do the following. Def test(): ... Simulation((ex_in_g)).run() #checks # nothing to return Regards, Chris |
From: Christopher F. <chr...@gm...> - 2011-12-23 13:56:04
|
You are correct, this currently is a limitation. Adding support for this is part on the MEP we recently created. Regard, Chris ** sent from mobile device ** On Dec 23, 2011 6:37 AM, "Oscar Diaz" <osc...@gm...> wrote: > Hi > > I was doing some experiments with the conversion function, and I found > a problem I'd like to discuss regarding access to members of data > structures inside generators. Suppose you have a dict with some > constants you need for the calculations: > > constants_list = {"myconst": 10} > def trans_block(clk, din, dout, const_list): > @always(clk.posedge) > def proc(): > dout.next = din + const_list["addconst"] > return instances() > > conversion fails with: > myhdl.ConversionError: in file simpletest.py, line 22: > Object type is not supported in this context: const_list, <type 'dict'> > > Same occur if you have a list: > myhdl.ConversionError: in file simpletest.py, line 22: > Object type is not supported in this context: const_list, <type 'list'> > > Or, even if you use an object with members accessed as attributes, like > this: > dout.next = din + const_list.addconst > conversion fails with: > myhdl.ConversionError: in file simpletest.py, line 29: > Unsupported attribute: addconst > > A workaround is to access data outside the generator, with another > variable name: > > constants_list = {"myconst": 10} > def trans_block(clk, din, dout, const_list): > addconst = const_list["addconst"] > @always(clk.posedge) > def proc(): > dout.next = din + addconst > return instances() > > However, it's kind of annoying to do that when you have a lot of > variables to access. Something similar occurs when you access signals. > > What are your thoughts? Is it good to allow access data members > whatever way you want or is better to have a fixed coding style? By > the way, I think these kind of details should be explained in the > conversion documentation. > > Best regards > > -- > Oscar Díaz > Key Fingerprint = 904B 306C C3C2 7487 650B BFAC EDA2 B702 90E9 9964 > gpg --keyserver subkeys.pgp.net --recv-keys 90E99964 > > I recommend using OpenDocument Format > for daily use and exchange of documents. > > http://www.fsf.org/campaigns/opendocument > > > ------------------------------------------------------------------------------ > Write once. Port to many. > Get the SDK and tools to simplify cross-platform app development. Create > new or port existing apps to sell to consumers worldwide. Explore the > Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join > http://p.sf.net/sfu/intel-appdev > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list > |
From: Oscar D. <osc...@gm...> - 2011-12-23 12:37:13
|
Hi I was doing some experiments with the conversion function, and I found a problem I'd like to discuss regarding access to members of data structures inside generators. Suppose you have a dict with some constants you need for the calculations: constants_list = {"myconst": 10} def trans_block(clk, din, dout, const_list): @always(clk.posedge) def proc(): dout.next = din + const_list["addconst"] return instances() conversion fails with: myhdl.ConversionError: in file simpletest.py, line 22: Object type is not supported in this context: const_list, <type 'dict'> Same occur if you have a list: myhdl.ConversionError: in file simpletest.py, line 22: Object type is not supported in this context: const_list, <type 'list'> Or, even if you use an object with members accessed as attributes, like this: dout.next = din + const_list.addconst conversion fails with: myhdl.ConversionError: in file simpletest.py, line 29: Unsupported attribute: addconst A workaround is to access data outside the generator, with another variable name: constants_list = {"myconst": 10} def trans_block(clk, din, dout, const_list): addconst = const_list["addconst"] @always(clk.posedge) def proc(): dout.next = din + addconst return instances() However, it's kind of annoying to do that when you have a lot of variables to access. Something similar occurs when you access signals. What are your thoughts? Is it good to allow access data members whatever way you want or is better to have a fixed coding style? By the way, I think these kind of details should be explained in the conversion documentation. Best regards -- Oscar Díaz Key Fingerprint = 904B 306C C3C2 7487 650B BFAC EDA2 B702 90E9 9964 gpg --keyserver subkeys.pgp.net --recv-keys 90E99964 I recommend using OpenDocument Format for daily use and exchange of documents. http://www.fsf.org/campaigns/opendocument |
From: Oscar D. <osc...@gm...> - 2011-12-22 20:17:58
|
2011/12/22 David Kitchen <dav...@in...>: > I am puzzled by traceSignals() generating 'Inconsistent hierarchy' > messages with the following code, but not if badBehaviour is False. > Note that the print at line 32 gives the same structure in both cases, > so its something I don't understand in the introspection. > I wanted to structure a collection of tests using a common library, and > this (bad) behaviour gets in the way of a natural expression of reuse. > > Example: > > #!/usr/bin/python > # example of strange behaviour in traceSignals() > badBehaviour = True > > from myhdl import * > > def ClkDriver(clk, halfperiod=5): > halfPeriod = delay(halfperiod) > @always(halfPeriod) > def driveClk(): > clk.next = 1 & ~clk > return driveClk > > def device_test(clk1, cd1): > clk2 = Signal(0) > cd2 = ClkDriver(clk2, halfperiod=3759) # in picoseconds to give > 7.5ns(133MHz) cycle > if badBehaviour: > return (cd2,) > else: > return cd1, cd2 > > def test(): > # make a clock generator > clk1 = Signal(0) > cd1 = ClkDriver(clk1, halfperiod=3759) # in picoseconds to give > 7.5ns(133MHz) cycle > if badBehaviour: > ret = (cd1,) + device_test(clk1, cd1) For some reason this is the sentence that causes the error. Try this: ret = (cd1, device_test(clk1, cd1)) Or even better, assign to a variable the output of device_test and use instances() to infer the return value. cd1 = ClkDriver(clk1, halfperiod=3759) # in picoseconds to give 7.5ns(133MHz) cycle dt_inst = device_test(clk1, cd1) return instances() Hope this helps you. > else: > ret = device_test(clk1, cd1) > print ret > return ret > > def process(timesteps): > # wrap in a tracer for vcd output > tr_out = traceSignals(test) > # simulate > sim = Simulation(tr_out) > sim.run(timesteps) > > if __name__ == '__main__': > timesteps = 1000 > process(timesteps) > > Dave Kitchen > > > ------------------------------------------------------------------------------ > Write once. Port to many. > Get the SDK and tools to simplify cross-platform app development. Create > new or port existing apps to sell to consumers worldwide. Explore the > Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join > http://p.sf.net/sfu/intel-appdev > _______________________________________________ > myhdl-list mailing list > myh...@li... > https://lists.sourceforge.net/lists/listinfo/myhdl-list Best regards -- Oscar Díaz Key Fingerprint = 904B 306C C3C2 7487 650B BFAC EDA2 B702 90E9 9964 gpg --keyserver subkeys.pgp.net --recv-keys 90E99964 I recommend using OpenDocument Format for daily use and exchange of documents. http://www.fsf.org/campaigns/opendocument |