any possibilty to check the correct behaviour of SoftCore CPU ? - Page 1
Forum section: electronics / general

author: legacy
author_rank: Super Contributor
timestamp: June 23, 2014, 11:24:25 am
content: hi guysi have an uncommon question, i friend of mine has developed a MIPS-1 (pipelined) SoftCore in VHDLand he has found there are issues (1) between what the binary code does and what it is expiated to be donehe says that, in same cases, the same binary code has a different behaviorso my question is: do you see any possibilty to check the correct behaviour of SoftCore CPU?I mean, a sort of automatic Hardware in the loop like:- For each existing opcode- Check against all rules- Is this a correct opcode? If yes, compare Hardware with a simulator or real mips-CPU.what do you think about ?apologies for the dummy question, i am new about this world(1) i have personally seen that compiling with gcc-mips has different behaviorfor example i got a piece of code that is working if compiled with -O0, -O1but that it is not working (and shows unexpected behavior) with -O2, -Osfor example, in this pseudo code i have observedCode:i=0;base=2;doan=an/base;i++; <---------- if observed, it grows with unexpected stepit is expected to grow like i=i+1it grows like i=i+1 if compiled with -O0, -O1but if compiled with -O2 the local variable "i" is filled with garbageloopas far as i know gcc-mips uses the -Ox, x={0,1,2,s} flag in order to do optimizationi don't exactly know what breaks things from -O1 to -O2but it may be something like- Hazards- Aleeor what else?

author: Jeroen3
author_rank: Super Contributor
timestamp: June 23, 2014, 11:33:25 am
content: QuoteExpected by the binary code, or expected by the programming language?The C(++) compiler might optimize some things away. Read the documentation for your compiler to find out what.After that the softcore should do as the binary says, if that is not the case then your vhdl synthesizer might have been wrong somewhere.Is the softcore shipped with a testbench?

author: legacy
author_rank: Super Contributor
timestamp: June 23, 2014, 11:55:17 am
content: Quote from: Jeroen3 on June 23, 2014, 11:33:25 amwe are talking about MIPS-1 target (with the SoftCore is compliant), sowith the same binary codethe SoftCore should have the same behavior of the ASIC (MIPS R3000), but in same cases it doesn't ant it shows unexpected behavior, i suspect due to a bug inside the HDL code.Quote from: Jeroen3 on June 23, 2014, 11:33:25 amyes it has, but it is a hard job to manually use the tb in order to check everything, and that is the question: is there a smarter way to do such a job ?

author: bwat
author_rank: Frequent Contributor
timestamp: June 23, 2014, 12:33:27 pm
content: Quote from: legacy on June 23, 2014, 11:24:25 amThis isn't uncommon at all with cheap and large FPGAs and free development tools making CPU design and implementation easier than ever. If I understand you correctly this is simply a case of checking that a CPU implementation is correct with respect to the specification (manufacturer's ISA description, definitional implementation, etc.). To me it sounds like your friend just hasn't done enough testing.1) Use the "-S" flag to look at the instruction stream. Compare and contrast the "-O1" and "-O2" options.2) Simulate the execution of the fault inducing code to see how being executed. Do the instructions flow through the pipeline correctly? Is the ALU being given the right operands and function selection code? Is the ALU result being fed into the register file? Is the result being stored in the right register? ......I'm guessing your branching is wrong. I have very little to back that up to be honest other than ALUs tend to fail in obvious ways that are caught easily.Good luck.Edit: Just saw this:Quote from: legacySo you have a test bench but you don't want to check.... hmmm.... I can't see any other way to be honest.

author: legacy
author_rank: Super Contributor
timestamp: June 23, 2014, 01:50:28 pm
content: Quote from: bwat on June 23, 2014, 12:33:27 pmyes, correct =)Quote from: bwat on June 23, 2014, 12:33:27 pmexactly, he said that he has manually tested the minimal part of the whole.Quote from: bwat on June 23, 2014, 12:33:27 pmi did, but i can't understand exactly where/why -O1 has good results, while -O2 and -Os has notQuote from: bwat on June 23, 2014, 12:33:27 pmi think i am too newly to afford this part, but my friend has much more skills in HDLQuote from: bwat on June 23, 2014, 12:33:27 pmok, i will consider this, thank your for your advices =)

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 09:16:24 am
content: what do you use to simulate ? and any tutorial about that ?

author: Jeroen3
author_rank: Super Contributor
timestamp: June 24, 2014, 09:36:18 am
content: Quote from: legacy on June 23, 2014, 01:50:28 pmhttp://en.wikipedia.org/wiki/Optimizing_compiler

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 10:04:25 am
content: Quote from: Jeroen3 on June 24, 2014, 09:36:18 ami know the theory, but i can't understand WHERE in the optimized code (exactly what/where/why) the optimization causes un expected behavior due to a problem in the pipeline: would you like to see the assembly code for -O0, -O1, -O2 and try to compare them ?

author: bwat
author_rank: Frequent Contributor
timestamp: June 24, 2014, 11:07:43 am
content: Yes, show us the assembly output.Edit: Make your test routine as small as possible and give us the output of "ggc -S -O1" and gcc -S -O2" to be more specific. It's been over 20 years since I worked with MIPS assembly but it's not that hard to get up and running with.

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 04:54:33 pm
content: this it the piece of C that has the issueCode:basen_result_t basen_value_to_ascii(uint32_t value,uint8_t ascii_value[],uint8_t mybase,uint32_t format_len){basen_result_t ans;uint32_t evaluated_digits_len;uint32_t required_format_len;uint32_t digits_offset;uint32_t An;uint32_t i;uint32_t j;uint32_t k;uint8_t ch;ans.is_valid = False;ans.value = value;ans.status = basen_result_ok;if (mybase <= 16){/* early evaluate of required format len */required_format_len = format_len;if (required_format_len>0){required_format_len--;}/* evaluate of digit len */An = value;i = 0;while ((An != 0)) // logicalAnd (i < basen_digit_n)){i++;An = An / mybase;}if ((required_format_len < string_safe_len)logicalAnd(i < string_safe_len)){evaluated_digits_len = i;/* check required_format_len */if (evaluated_digits_len >= required_format_len){/** fix1*/required_format_len = evaluated_digits_len;}/* evaluate format offset */if (required_format_len > 0){/** offset case A* do format digits*/digits_offset = required_format_len - evaluated_digits_len;}else{/** offset case B* do not format digits*//* do not format digits */digits_offset = 0;}/* zero stuffing */for (i = 0; i < required_format_len; i++){ascii_value = '0';}ascii_value = '\0';/* evaluate */An = value;i = 0;do{/** is the mips1 bug here ???*/j = (evaluated_digits_len - i) + digits_offset;k = (An % mybase);ch=basen_digit;ascii_value = ch;An = An / mybase;i++; // <-------------------- unexpected behavior happens here, i++ is not i incremented correctly} while (An != 0);j = (evaluated_digits_len + digits_offset + 1);ascii_value = '\0';ans.is_valid = True;}else{/** failure1*/ascii_value = '\0';ans.status = basen_result_not_defined;}}else{/** failure2*/ascii_value = '\0';ans.status = basen_result_unsupported_base;}return ans;}this is the gcc-mips ENV used in the build upCode:MY_CC=mips-elf-gcc -G0 -fPIE -O0 -mips1 -N -mno-check-zero-division -mdivide-breaks -mno-gpoptCode:MY_CC=mips-elf-gcc -G0 -fPIE -O1 -mips1 -N -mno-check-zero-division -mdivide-breaks -mno-gpoptCode:MY_CC=mips-elf-gcc -G0 -fPIE -O2 -mips1 -N -mno-check-zero-division -mdivide-breaks -mno-gpoptthis is the assembly with -O0, no unexpected behaviorCode:basen_value_to_ascii:.frame$fp,56,$31# vars= 48, regs= 1/0, args= 0, gp= 0.mask0x40000000,-4.fmask0x00000000,0.setnoreorder.setnomacroaddiu$sp,$sp,-56sw$fp,52($sp)move$fp,$spmove$2,$4sw$5,60($fp)sw$6,64($fp)move$3,$7sb$3,68($fp)sw$0,32($fp)lw$3,60($fp)nopsw$3,36($fp)li$3,1# 0x1sw$3,40($fp)lbu$3,68($fp)nopsltu$3,$3,17beq$3,$0,$L40noplw$3,72($fp)nopsw$3,24($fp)lw$3,24($fp)nopbeq$3,$0,$L41noplw$3,24($fp)nopaddiu$3,$3,-1sw$3,24($fp)$L41:lw$3,60($fp)nopsw$3,16($fp)sw$0,12($fp)b$L42nop$L43:lw$3,12($fp)nopaddiu$3,$3,1sw$3,12($fp)lbu$3,68($fp)lw$4,16($fp)nopdivu$0,$4,$3mfhi$4mflo$3sw$3,16($fp)$L42:lw$3,16($fp)nopbne$3,$0,$L43noplw$3,24($fp)nopsltu$3,$3,40beq$3,$0,$L44noplw$3,12($fp)nopsltu$3,$3,40beq$3,$0,$L44noplw$3,12($fp)nopsw$3,28($fp)lw$4,28($fp)lw$3,24($fp)nopsltu$3,$4,$3bne$3,$0,$L45noplw$3,28($fp)nopsw$3,24($fp)$L45:lw$3,24($fp)nopbeq$3,$0,$L46noplw$4,24($fp)lw$3,28($fp)nopsubu$3,$4,$3sw$3,20($fp)b$L47nop$L46:sw$0,20($fp)$L47:sw$0,12($fp)b$L48nop$L49:lw$4,64($fp)lw$3,12($fp)nopaddu$3,$4,$3li$4,48# 0x30sb$4,0($3)lw$3,12($fp)nopaddiu$3,$3,1sw$3,12($fp)$L48:lw$4,12($fp)lw$3,24($fp)nopsltu$3,$4,$3bne$3,$0,$L49noplw$4,64($fp)lw$3,12($fp)nopaddu$3,$4,$3sb$0,0($3)lw$3,60($fp)nopsw$3,16($fp)sw$0,12($fp)$L50:lw$4,28($fp)lw$3,12($fp)nopsubu$4,$4,$3lw$3,20($fp)nopaddu$3,$4,$3sw$3,8($fp)lbu$3,68($fp)lw$4,16($fp)nopdivu$0,$4,$3mfhi$3sw$3,4($fp)lw$4,4($fp)lui$3,%hi(basen_digit)addiu$3,$3,%lo(basen_digit)addu$3,$4,$3lb$3,0($3)nopsb$3,0($fp)lw$4,64($fp)lw$3,8($fp)nopaddu$3,$4,$3lbu$4,0($fp)nopsb$4,0($3)lbu$3,68($fp)lw$4,16($fp)nopdivu$0,$4,$3mfhi$4mflo$3sw$3,16($fp)lw$3,12($fp)nopaddiu$3,$3,1sw$3,12($fp)lw$3,16($fp)nopbne$3,$0,$L50noplw$4,28($fp)lw$3,20($fp)nopaddu$3,$4,$3addiu$3,$3,1sw$3,8($fp)lw$4,64($fp)lw$3,8($fp)nopaddu$3,$4,$3sb$0,0($3)li$3,1# 0x1sw$3,32($fp)nopb$L52nop$L44:lw$3,64($fp)nopsb$0,0($3)sw$0,40($fp)b$L52nop$L40:lw$3,64($fp)nopsb$0,0($3)li$3,32# 0x20sw$3,40($fp)$L52:lw$5,32($fp)lw$4,36($fp)lw$3,40($fp)sw$5,0($2)sw$4,4($2)sw$3,8($2)move$sp,$fplw$fp,52($sp)addiu$sp,$sp,56j$31nopthis is the assembly with -O1, no unexpected behaviorCode:basen_value_to_ascii:.frame$sp,0,$31# vars= 0, regs= 0/0, args= 0, gp= 0.mask0x00000000,0.fmask0x00000000,0.setnoreorder.setnomacromove$2,$4lw$3,16($sp)andi$7,$7,0x00ffsltu$4,$7,17beq$4,$0,$L43nopbeq$3,$0,$L45move$8,$3addiu$8,$3,-1$L45:beq$5,$0,$L47move$3,$0move$9,$5$L48:divu$0,$9,$7mflo$9bne$9,$0,$L48addiu$3,$3,1$L47:sltu$4,$8,40beq$4,$0,$L49nopsltu$4,$3,40beq$4,$0,$L49nopsltu$4,$3,$8beq$4,$0,$L50move$9,$3move$9,$8$L50:beq$9,$0,$L52move$10,$0move$4,$0li$10,48# 0x30addu$8,$6,$4$L60:sb$10,0($8)addiu$4,$4,1sltu$8,$4,$9bne$8,$0,$L60addu$8,$6,$4subu$10,$9,$3$L52:addu$9,$6,$9sb$0,0($9)addu$4,$10,$3addu$4,$6,$4move$8,$5lui$9,%hi(basen_digit)addiu$9,$9,%lo(basen_digit)$L54:divu$0,$8,$7mfhi$8addu$8,$8,$9lbu$8,0($8)nopsb$8,0($4)mflo$8bne$8,$0,$L54addiu$4,$4,-1addu$6,$6,$3addu$10,$6,$10sb$0,1($10)li$3,1# 0x1b$L55li$4,1# 0x1$L49:sb$0,0($6)move$3,$0b$L55move$4,$0$L43:sb$0,0($6)move$3,$0li$4,32# 0x20$L55:sw$4,8($2)sw$5,4($2)j$31sw$3,0($2)this is the assembly with -O2, unexpected behavior, the local variable is out of rangeCode:basen_value_to_ascii:.frame$sp,0,$31# vars= 0, regs= 0/0, args= 0, gp= 0.mask0x00000000,0.fmask0x00000000,0.setnoreorder.setnomacroandi$7,$7,0x00ffsltu$3,$7,17lw$8,16($sp)beq$3,$0,$L47move$2,$4beq$8,$0,$L49nopaddiu$8,$8,-1$L49:beq$5,$0,$L51move$3,$0move$9,$5$L52:divu$0,$9,$7mflo$9bne$9,$0,$L52addiu$3,$3,1$L51:sltu$4,$8,40beq$4,$0,$L53sltu$4,$3,40beq$4,$0,$L53sltu$4,$3,$8beq$4,$0,$L54subu$10,$8,$3$L55:move$4,$0li$12,48# 0x30$L58:addu$11,$6,$4addiu$4,$4,1sltu$9,$4,$8bne$9,$0,$L58sb$12,0($11)$L57:addu$8,$6,$8addu$4,$10,$3lui$9,%hi(basen_digit)sb$0,0($8)addu$4,$6,$4addiu$9,$9,%lo(basen_digit)move$8,$5$L59:divu$0,$8,$7mfhi$8addu$8,$9,$8lbu$11,0($8)mflo$8sb$11,0($4)bne$8,$0,$L59addiu$4,$4,-1addu$3,$6,$3addu$10,$3,$10li$4,1# 0x1li$3,1# 0x1sb$0,1($10)sw$4,8($2)sw$5,4($2)j$31sw$3,0($2)$L47:move$3,$0li$4,32# 0x20sb$0,0($6)sw$4,8($2)sw$5,4($2)j$31sw$3,0($2)$L53:move$3,$0move$4,$0sb$0,0($6)sw$4,8($2)sw$5,4($2)j$31sw$3,0($2)$L54:bne$3,$0,$L56nopmove$8,$0b$L57move$10,$0$L56:move$8,$3b$L55move$10,$0

author: nctnico
author_rank: Super Contributor
timestamp: June 24, 2014, 05:03:43 pm
content: I'd try to reduce the piece of code to a smaller one with a loop. A weird quirk of the MIPS architecture is that it also executes the instruction after a branch or jumps. That is why you see so many nops after branches/jumps in the unoptimised code. Maybe that is what is going wrong.If you could somehow single step through the code it would show where it goes wrong.

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 05:06:38 pm
content: About the unexpected behavior, as the fact that basen_digit is an array of char defined this wayCode:basen_digit:.ascii"0123456789ABCDEF????\000"if the local variable "i" is not incremented in the right way (i=i+1) it causes the variable "j" to be wrong tooCode:j = (evaluated_digits_len - i) + digits_offset;In particular it seems that j becomes negative (which is impossible for its range check, see the code, it could only happens if "i" is extremely out of range, which is impossible because of the increment inside the loop)btw, if it happens then "j" will not point to the right charCode:ascii_value = chSo i observe a completely wrong ascii_value in the uart terminalCode:do{/** is the mips1 bug here ???*/j = (evaluated_digits_len - i) + digits_offset;k = (An % mybase);ch=basen_digit;ascii_value = ch;An = An / mybase;i++; // <-------------------- unexpected behavior happens here, i++ is not i incremented correctly} while (An != 0);Wandering why, what is causing it

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 05:11:55 pm
content: Quote from: nctnico on June 24, 2014, 05:03:43 pmi do not have such tool,gdb-stub(which is a part of gnu debugger) is not working for this SoC (i have to fix a lot of thing, also the "break" instruction is used by gdb-stub but the SoftCore has no "break" implementation, so i can't use it): in other words i can't debug on this target step by step, i have no jtag tap machine in the HDL code … so i can do step by step on VHDL simulator (e.g. gtkWave + gHDL), or with an other MIPS machinep.s.i put all these assembly code (-O0, -O1, -O2) on a real ASIC MIPS, such is my Atlas-MIPS32-R2 board, and i have no issue, ok it is not MIPS1 as the Softcore, but … it may be i could exclude- a bug in the C source code- a bug in the toolchain- a bug in the Env

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 05:15:35 pm
content: Quote from: nctnico on June 24, 2014, 05:03:43 pmis there a flag (or a pretty/ugly trick workaround) to force gcc-mips to put a "nop" after each conditional/unconditional branch ?

author: andersm
author_rank: Super Contributor
timestamp: June 24, 2014, 06:22:20 pm
content: Here's the inner loop, -O1 version, annotated:Code:# $9 = &(basen_digit)# $8 = An# $7 = mybase# $4 = &(ascii_value[evaluated_digits_len+digits_offset+max_i])$L54:divu $0,$8,$7 # divmod(An, mybase)mfhi $8 # k = remainderaddu $8,$8,$9 # $8 = &(basen_digit)lbu $8,0($8) # ch = basen_digitnopsb $8,0($4) # ascii_value = chmflo $8 # $8 = quotient, An = An / mybasebne $8,$0,$L54 # if An != 0, jump to L54addiu $4,$4,-1 # decrease ascii_value pointer, executed in delay slotHere is the -O2 version:Code:$L59:divu $0,$8,$7mfhi $8addu $8,$9,$8lbu $11,0($8)mflo $8sb $11,0($4)bne $8,$0,$L59addiu $4,$4,-1The only significant difference is that register $8 is changed by the mflo instruction immediately after being used as the address for a memory load. It should be trivial to construct a test case to show if there is a pipeline error here.

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 06:51:15 pm
content: may be also "lbu" has an hazard ?

author: andersm
author_rank: Super Contributor
timestamp: June 24, 2014, 07:06:24 pm
content: There shouldn't be, but if the pipeline is buggy who knows? There is a hazard between mflo and the divu of the next loop iteration, but there are more than the two required instructions between them.

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 07:58:09 pm
content: i have reported everything to the HDL guy, the one who has put this project on.what are your advices in order to help me (and him) to identify exactly what is buggy ? let me know if i could arrange something by firmware, he will try to simulate everything on HDL simulator (and, may be i will learn how to do it, too)

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 09:13:29 pm
content: also, why if i wrote this assembly code (base.s)Code:.text.align 2.global entryentry:.set noreorderStartTest:li $9, 0x4li $8,0x2000li $7,0x7$L54:divu $8,$7mfhi $8addu $8,$9,$8lbu $11,0($8)mflo $8bne $8,$0,$L54addiu $4,$4,-1and i invokeCode:mips-elf-as base.s -o base.omips-elf-ld base.o -Ttext 0 -eentry -o base.elfmips-elf-objdump -D --headers -S base.elfi got this dissembled code ?Code:Disassembly of section .text:00400000 <entry>:400000:24090004lit1,4400004:24082000lit0,8192400008:24070007lia3,740000c:14e00002bneza3,400018 <entry+0x18> <-----------???400010:0107001bdivuzero,t0,a3400014:0007000dbreak0x7 <----------------???400018:00004012mflot040001c:00004010mfhit0400020:01284021addut0,t1,t0400024:910b0000lbut3,0(t0)400028:00004012mflot040002c:1500fff7bnezt0,40000c <entry+0xc>400030:2484ffffaddiua0,a0,-1

author: andersm
author_rank: Super Contributor
timestamp: June 24, 2014, 09:23:32 pm
content: It's a generateddivision by zero check:Quote

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 09:32:47 pm
content: is it possible to remove it ? i need the test as i have written without any add on

author: andersm
author_rank: Super Contributor
timestamp: June 24, 2014, 10:02:33 pm
content: You have to write the instruction in the three-operand format with zero as the destination register.Code:divu $0,$8,$7

author: legacy
author_rank: Super Contributor
timestamp: June 24, 2014, 11:44:53 pm
content: thanks, it compiles in the right way

author: legacy
author_rank: Super Contributor
timestamp: June 25, 2014, 11:32:01 am
content: just to understand things, what is the different betweendivu zero,Rx,Ryanddivu Rx,Ry ?in other words whymips-asis taking different action if i use zero as the destination register ?

author: bwat
author_rank: Frequent Contributor
timestamp: June 25, 2014, 12:24:49 pm
content: I haven't touched MIPS assembly since 1991/1992 but isn't $0 always zero so writes to that register are ignored? Hopefully a MIPS expert will give you a proper answer.What I wanted to say was you're probably going to have to build a test suite. Relying on GCC generated code to exercise your CPU probably wont exercise your datapath and control unit completely. It's also much easier to test each component individually in the HDL of your choice that trying to write target programs to do the same thing. When you're satisfied the separate modules of your CPU work then you might want to run some compiled code. Just a suggestion.

author: andersm
author_rank: Super Contributor
timestamp: June 25, 2014, 01:46:52 pm
content: The integer division instructions never generate exceptions, so if you need to detect division by zero errors, it must be tested for in software. The two-operand format is normally a macro that inserts this test automatically. The three-operand version with zero as target is an assembler mnemonic that specifically bypasses the macro. The operation results (quotient and remainder) are always generated into the lo and hi registers.The MIPS assembly language defines a relatively large number of macros, pseudo-instructions and "smart assembler" behaviour that unfortunately is not very well documented. The book "See MIPS Run" is the best resource I've encountered, but even there the information is not collected in one place.

author: legacy
author_rank: Super Contributor
timestamp: June 25, 2014, 07:49:39 pm
content: @andersmthank you, it's 100% clear to me now

author: legacy
author_rank: Super Contributor
timestamp: June 25, 2014, 07:52:38 pm
content: Quote from: bwat on June 25, 2014, 12:24:49 pmyes, good advice, the Truth is that … the guy who has built this project hasn't tested it hardly, he said "yes" but it is a lie, i mean he has been working on such a SoC for 3 years so he has though that so long time is enough to be sure of his job. The Truth is … he has never tested so deeply, and he has never put a real complex application on, he has tested just a few parts with extremely simplified context, and this is the reason why he has has asked me to try his SoC with something from the real world, so i have putted a bit of real world routines on, and bang now we all know that the pipeline is buggyAs i wrote, i am not good at HDL, i am just trying to help, and in order to do that, i am planning to split the testing activity into two+1 sub activities1) asking an HDL friend of mine to hardly put everything on modelsim writing a lot of test-benches (i have to learn about it, i am not good at, i can't directly help)2) asking an other friend to use his chip scope (Xilinx technology) in order to understand exactly what is wrong using Spartan3E and Spartan6 boards3) supporting them with testing application, such as assembly code with positive/negative test cases, etci hope that combining them will demystify thingsas "firmware guy" as far as i have observed, i can say:1) adding NOP after branches avoids unexpected behavior2) adding NOP after load/store avoids unexpected behaviorthe -O0 is the winning one, it has always had success with every kind of complex application i have putted on such a SoC: never seen any unexpected behavior with -00, i thing because it is working exactly this way: stuffing a lot of NOP in order to avoid hazardsbut it also may be the real cause is related to collision to registers from/to the mux, or other things that i think may be clarified by the Chip-Scope.I don't know very well this technology, but if i have understood right the "Chip-scope" is a Logic Analyzer from Xilinx, unfortunately it is not included in the ISE web pack that i have (ISE v10.1/linux, and ISE v14/windows), my friend has a full license so he could use it.

author: legacy
author_rank: Super Contributor
timestamp: June 26, 2014, 03:53:11 pm
content: I am planning to buythisled stick in order to see the PC, or other registers

author: legacy
author_rank: Super Contributor
timestamp: June 26, 2014, 03:58:17 pm
content: anybody experienced with such a problem/equipment ?

author: nctnico
author_rank: Super Contributor
timestamp: June 26, 2014, 04:34:46 pm
content: IMHO the best approach is to simulate the MIPS1 core fully. First test each part/subsystem and document what it should do. Then simulate it as a whole.

author: legacy
author_rank: Super Contributor
timestamp: June 26, 2014, 05:01:52 pm
content: with gHDL plus GTKwave ?if my friend doesn't do it, i will do by myselfbut … i have to learn about it (never done my life)

author: nctnico
author_rank: Super Contributor
timestamp: June 26, 2014, 05:37:30 pm
content: One of the things you need to be aware of when using GHDL is that you can only have 1 clock signal for one clock. If you split a clock into multiple signals you get weird effects.

author: bwat
author_rank: Frequent Contributor
timestamp: June 27, 2014, 05:36:12 am
content: Quote from: legacy on June 25, 2014, 07:52:38 pmEvery CPU design I've ever seen on the net has bugs. I only use my own designs these days. Checking someone else's takes as much time as checking your own. Writing your own from scratch isn't that difficult.You may not have a working CPU but you're a lot wiser when it comes to people and their definitions of "tested". Good luck!

author: legacy
author_rank: Super Contributor
timestamp: June 27, 2014, 08:20:06 am
content: but i am not skilled enough to write such a complex design from scratches

author: nctnico
author_rank: Super Contributor
timestamp: June 27, 2014, 08:50:57 am
content: Although the MIPS1 core is mighty interesting I suggest to use the Lattice Mico 32 core from Lattice. That design has been thouroughly tested and is useable in production designs.

author: legacy
author_rank: Super Contributor
timestamp: June 27, 2014, 03:57:10 pm
content: the topic is related about how we could fix it, 'cause we have to fix it, that's all folks

author: legacy
author_rank: Super Contributor
timestamp: June 27, 2014, 04:09:28 pm
content: if anyone want to collaborate, fix things, have fun with such a SoC, feel feel to contact me by PM

author: nctnico
author_rank: Super Contributor
timestamp: June 27, 2014, 04:13:00 pm
content: Then chop it up to parts and test each partWhat is the experience level of the author of the core? If it is a project for a thesis or internship you may be in for some nasty surprises. Another thing to look at is the level of documentation and comments. If the code is clearly commented it is easier to understand what it is supposed to do. Unfortunately I can only offer advice; I already have a large back log of hobby projects.

author: legacy
author_rank: Super Contributor
timestamp: June 27, 2014, 08:04:34 pm
content: Quote from: nctnico on June 27, 2014, 04:13:00 pmit's easy for you, but … not for me, yetit's just a tiny SoC with {CPU - RAM/ROM - UART} and nothing else (so it is easy, isn't it ? i have seen much more complex projects, e.g. The OpenRisc-One), but it appears to me as the largest and most complex HDL project i have ever seen. I am not experienced about, and the biggest project i have done up today is around "tiny devices", i mean something like VHDL code for uart, SPI master, and little things like them, i have never realized/debugged a SoC, and never toyed with the HDL code of a SoftCore.Quote from: nctnico on June 27, 2014, 04:13:00 pmwell, i got nasty surprises when i put -O2 firmware and i got unexpected behavior, i was thinking the SoftCore was stable because he said "tested" and "i have been working on it for 3 years", i think he got started bythisproject, of which he has reused a few ideas, working model and a some of tools.Quote from: nctnico on June 27, 2014, 04:13:00 pmgreat mess, great deal, there is no documentation, and before me there was no firmware examples, no working toolchain. After fighting a bit with a lot of issues now it is possible to compile complex projects and to easily convert an elf into a memory model file to be used in the synthesis process.The power of a toolchain plus its tools and libraries on your finger tips: just a script'call to build everything !Quote from: nctnico on June 27, 2014, 04:13:00 pmUnfortunately there are still no comments in the VHDL code, but it seems written into an easy going way.

author: nctnico
author_rank: Super Contributor
timestamp: June 27, 2014, 08:15:41 pm
content: I don't know where you are in your carreer but if you take this project on you'll learn a lot and it is definitely something to put on your CV. IMHO time well spend.

author: legacy
author_rank: Super Contributor
timestamp: June 28, 2014, 08:28:51 am
content: before reinventing the wheel, i'd check if there is an assembly monitor for MIPS1, something extremely easy that eats a few bytes in order to provide the following features- memory view, aka dump, something like "DM 1000.0000 100", let me see the first 100 bytes starting from 1000.0000- memory fill- load, … from SRECthe less it eats about byte code in iRam the better it is (i have 8Kbyte of BRAM for the total)anything around ? if no, i will implement by myself

author: nctnico
author_rank: Super Contributor
timestamp: June 28, 2014, 10:32:30 am
content: Such a thing is not difficult to implement BUT it won't help you. What you need is a testbench (or better said: test vectors) for the MIPS1 processor to verify it's design at the simulation stage. If you are going to throw random code at it the chances are very high you won't discover all the bugs.This might be interesting for testing the MIPS1:http://probell.com/pubs/I223.PDFI did not read it but the first page has all the right buzz-words.

author: legacy
author_rank: Super Contributor
timestamp: June 28, 2014, 12:17:23 pm
content: A monitor helps me a lot!Simulating is nothing if you don't know where to look for, i have told you several and several times that i have not so much resources, time, and skills to do a full simulation! So i need a boot loader monitor in the real fpga target in order to load real binaries in order to be helped about which part of the simulation it takes the most importance to be analyzed in details !Also i prefer this way because my PC (intel dual core2, @1.6Ghz) takes more than 20 minutes to synthesize the whole SoC and it means that if you want to modify an assembly line it will take an other 20 minutes to let it checked out!Altera has different way to load an elf inside the SoC ram, as far as i understand it seems to me that Xilinx has a very complicated tool which could be used to load an elf into BRAM, ad this (in case of spartan3e) may be possible only if you use their "b16-bram-model", so … i have written my own converter tool which loads and elf and converts it into a vhdl file that is putted in the synthesis tree.caseA: without a boot loader, any changes to any assembly or c code causes a new vhdl file, that cause a new synthesis, that takes 20 minutescaseB: with a boot loader, any changes to any assembly or c code cause a rebuild of the srec file, that cause a new target-reset + host-to-target download, that takes less than 1 second (at 115200bps, and it can be 4x faster)btw, i have found nothing around, i have modified the actual "calculator" firmware in order to recycle a few code in order to arrange a tiny boot loader with SREC S3-ONLY. For such a purpose i have also forced objdump to provide 4 byte address ONLY elf-to srec-conversion.The good news is that it works and i am able to upload whatever i want on the real fpga, the bad news is … this monitor eats 4Kbyte of BRAM, 50% of my planned resources

author: bwat
author_rank: Frequent Contributor
timestamp: June 28, 2014, 01:00:58 pm
content: Quote from: legacy on June 28, 2014, 12:17:23 pmYou want to run a monitor on a broken CPU!Quote from: legacy on June 28, 2014, 12:17:23 pmAnd it has been suggested several times that you should break the whole into manageable parts and test these individually. After these have been shown to pass your tests, you start combining them into bigger blocks and test these - you might even just start testing the CPU on instruction streams at this point. You're trying to change the problem to suit your experience - change your experience to suit the problem instead!How I test my multiplexers. I work in Verilog so you'll have to figure out how to do something similar to this in VHDL.1) The test bench in Verilog (mux_tb.v):Code:module mux_tb;reg [15:0] A0, A1, A2, A3, A4, A5, A6, A7, A8;reg [15:0] A9, A10, A11, A12, A13, A14, A15;regS_2;regS1, S0;reg [2:0] S_8;reg [3:0] S_16;wire [15:0] X_2, X_4, X_8, X_16;integer handle;multiplexer_2_1 dut2(X_2, A0, A1, S_2);multiplexer_4_1 dut4(X_4, A0, A1, A2, A3, S1, S0);multiplexer_8_1 dut8(X_8, A0, A1, A2, A3, A4, A5, A6, A7, S_8);multiplexer_16_1 dut16(X_16, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, S_16);initial begin$dumpfile("mux.vcd");$dumpvars(0,dut2);$dumpvars(0,dut4);$dumpvars(0,dut8);$dumpvars(0,dut16);handle = $fopen("mux_tb.out");A0 <= 16'h0;A1 <= 16'h1;A2 <= 16'h2;A3 <= 16'h3;A4 <= 16'h4;A5 <= 16'h5;A6 <= 16'h6;A7 <= 16'h7;A8 <= 16'h8;A9 <= 16'h9;A10 <= 16'ha;A11 <= 16'hb;A12 <= 16'hc;A13 <= 16'hd;A14 <= 16'he;A15 <= 16'hf;S_2 <= 0;#1 $fdisplay(handle, "%d %d", X_2, S_2);S_2 <= 1;#1 $fdisplay(handle, "%d %d", X_2, S_2);S1 <= 0; S0 <= 0;#1 $fdisplay(handle, "%d %d", X_4, 0);S1 <= 0; S0 <= 1;#1 $fdisplay(handle, "%d %d", X_4, 1);S1 <= 1; S0 <= 0;#1 $fdisplay(handle, "%d %d", X_4, 2);S1 <= 1; S0 <= 1;#1 $fdisplay(handle, "%d %d", X_4, 3);S_8 <= 0;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 1;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 2;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 3;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 4;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 5;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 6;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_8 <= 7;#1 $fdisplay(handle, "%d %d", X_8, S_8);S_16 <= 0;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 1;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 2;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 3;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 4;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 5;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 6;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 7;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 8;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 9;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 10;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 11;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 12;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 13;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 14;#1 $fdisplay(handle, "%d %d", X_16, S_16);S_16 <= 15;#1 $fdisplay(handle, "%d %d", X_16, S_16);#1 $finish;endendmodule2) The generated output file (mux_tb.out) with the resultsCode:0 01 10 01 12 23 30 01 12 23 34 45 56 67 70 01 12 23 34 45 56 67 78 89 910 1011 1112 1213 1314 1415 153) The program which checks the test results (mux_tb.c).Code:/* mux_tb.c */#include <stdio.h>/* #define DEBUG */int mux (void);/** Test the multiplexers.*/int main(int argc, char **argv){(void) argc;(void) argv;while(!feof(stdin)){if(!mux()){return -1;}}return 0;}/** Read a line and make sure it is correct.* Return 0 on failure and 1 on success.*/int mux (void){int X;int S;if(scanf("%d %d\n", &X, &S) < 0){fprintf(stderr, "Scan error\n");return 0;}#ifdef DEBUGprintf("Verifying %d %d\n", X, S);#endifreturn X == S;}4) Part of the Makefile which creates and runs the mux test (mux.v is my Verilog file containg code for my multiplexers):Code:###### MUX###test_mux: mux_tb mux.v tb/mux_tb.viverilog -o tb/mux mux.v tb/mux_tb.v(cd tb; vvp mux)(cd tb; ./mux_tb < mux_tb.out)mux_tb: tb/mux_tb(cd tb; ${CC} -o mux_tb mux_tb.c)

author: legacy
author_rank: Super Contributor
timestamp: June 28, 2014, 02:14:15 pm
content: Quote from: bwat on June 28, 2014, 01:00:58 pmi have written several and several time that it is not completely broken, if compiled with -O0 everything is working, while if compiled with -O1/-O2 it is not, in fact the the monitor is written in C, recycling an other piece of C code, it has been compiled with -O0 and it is working: it passes all the internal tests, it loads srec, it dumps ram, and i am fine with it!Quote from: legacy on June 28, 2014, 12:17:23 pmyour example is for a mux, that is less 1% of the job you have to do to check a SoC which is much more complex (we are talking about 2000 lines of VHDL, just to summarize), so I will simulate, but the monitor will help me about what to put in the "to be watched" list with thehighest priority, for example i suspect the bug is related to MUL, so i will consider this module for the first.

author: bwat
author_rank: Frequent Contributor
timestamp: June 28, 2014, 02:30:53 pm
content: Quote from: legacy on June 28, 2014, 02:14:15 pmYou don't know that for sure as it's untested.Quote from: legacy on June 28, 2014, 12:17:23 pmOf course it's just a fraction. It was given as an example of the type of test you should be creating.I'm currently in the middle of a 16-bit microcoded CISC CPU implementation. I've written 1641 lines of Verilog for the CPU so far. As for the tests, I've written 3215 lines of Verilog and C. That's nearly double! The CPU implementation is 99% done so when I finish testing each instruction with each of the eight addressing modes I'll probably end up with 5 to 10 times as much test code as CPU implementation code.Developing CPUs takes time and effort.Quote from: legacy on June 28, 2014, 02:14:15 pmI suspect you're in for a shock.

author: legacy
author_rank: Super Contributor
timestamp: June 28, 2014, 09:15:37 pm
content: Quote from: bwat on June 28, 2014, 02:30:53 pmI am curious, which one ?I do not have any 16-bit in my experiencesQuote from: bwat on June 28, 2014, 02:30:53 pmYes, i am understanding how hard it is X_X

author: bwat
author_rank: Frequent Contributor
timestamp: June 28, 2014, 09:37:05 pm
content: Quote from: legacy on June 28, 2014, 09:09:44 pmThat's why I wrote that you didn't know everything worked with no compiler optimisations. But with every bug you find and fix, there's fewer to trip you up in the future. Slowly but surely you're getting there.Quote from: legacy on June 28, 2014, 09:15:37 pmIt's just a design from a book. I'm implementing it for more experience in microcoded control unit design. I've only implemented simple microcoded designs up to now:microcoded control unit example 1microcoded control unit example 2.I've got plans to implement a series of lambda calculus reduction engines in FPGA and they'll be easier with microcoded control units so what I'm doing now is good practice.Quote from: legacy on June 28, 2014, 09:15:37 pmYep, but the harder it is, the more we learn. Keep on keeping on and good luck!

author: legacy
author_rank: Super Contributor
timestamp: July 02, 2014, 01:03:02 pm
content: just googling around i have foundthis"Leon" SoftCore an i am impressed about it