Cannot include define file in verilog - cpu

I am using ModelSim to simulate Verilog. I have created one define.v file and want to include this define.v in multiple other verilog modules.
part of define.v is as follows:
// defines
`define RSIZE 4
`define ISIZE 16
`define DSIZE 16
`define ASIZE 16
`define NREG 4
`define ADD 4'b0000
`define SUB 4'b0001
`define AND 4'b0010
`define OR 4'b0011
`define SLL 4'b0100
`define SRL 4'b0101
`define SRA 4'b0110
`define RL 4'b0111
`define LW 4'b1000
`define SW 4'b1001
`define LHB 4'b1010
`define LLB 4'b1011
`define BR 4'b1100
`define JAL 4'b1101
`define JR 4'b1110
`define EXEC 4'b1111
...
...
I have include this file in multiple other modules, for instance: the alu.v
//ALU.v
`include "define.v"
module alu(
input [`DSIZE-1:0] a, b, //operands
input [3:0] op, //operation code
input [3:0] imm, //immediate
output reg [`DSIZE-1:0] out, //output
output reg [2:0] flag //flag for N, V, Z in sequence
);
...
...
However, while compiling, it seems that the define file is not included, the error is as follows:
** Error: //psf/Home/Desktop/Projects/project1/alu.v(3):
Cannot open `include file "define.v".
How could I solve this problem?

If define.v is not within the current directory you need to instruct Modelsim to use the directory containing define.v when searching for files which are included.
The option to do this is +incdir+path.
So, for example, if you have the following file structure:
project/src/alu.v
project/include/define.v
And you run from project, then you need to include +incdir+include as an argument to Modelsim.
As a side note, if you are including the same file more than once, you should use "include guards" to avoid warnings about macros being redefined.
`ifndef DEFINE_V
`define DEFINE_V
`define RSIZE 4
`define ISIZE 16
....
`endif

Related

Why does gcc not optimize the immediate?

Regardless of the optimization level, a pointer loaded with an immediate value at the assembly level is loaded a slightly different value, being corrected using a fixed offset when dereferenced.
E.g
int test(){
int *tmp = (int*)0x30000004;
tmp[0]++;
return tmp[1];
}
Compiled with mips-linux-gnu-gcc-8 -O3 -nostdlib test.c -c generates the following assembly:
Disassembly of section .text:
00000000 <test>:
0: 3c033000 lui v1,0x3000
4: 8c640004 lw a0,4(v1)
8: 8c620008 lw v0,8(v1)
c: 24840001 addiu a0,a0,1
10: 03e00008 jr ra
14: ac640004 sw a0,4(v1)
As you can see the $v1 register is loaded with 0x30000000 and then the offsets are all shifted by +4.
Why does GCC do this?
Is it possible to deactivate?
The end goal would be to get something like this:
Disassembly of section .text:
00000000 <test>:
li v1,0x30000004
lw a0,0(v1)
lw v0,4(v1)
addiu a0,a0,1
jr ra
sw a0,0(v1)
The expected result changes as soon optimizations are enabled, -O1.
After testing with -O1 + -fno* flags to turn it into -O0 I've come to the conclusion there's an hidden optimization going on that can't be disabled at the moment.
Related: g++ O1 is not equal to O0 with all related optimization flags
Since the hidden optimization can't be disabled I'll just use the older version of the compiler that outputs as expected.

GCC adding dereference where there shouldn't be

I'm using gcc to compile for mips32, and I declare a pointer to a struct called OSEvent within a global scope as follows:
OSEvent *__osMainEventQueue = NULL;
Additionally, code from within a certain function references this pointer during a call to a function:
__osEnqueueEvent(event, __osMainEventQueue);
That function is declared as follows:
extern void __osEnqueueEvent (OSEvent *event, OSEvent *queue);
However, when debugging this code, gcc seems to dereference the pointer to __osMainEventQueue despite me putting nothing there. You can see this in the disassembly as follows:
118: 3c020000 lui v0,0x0
118: R_MIPS_HI16 __osMainEventQueue
11c: 8c420000 lw v0,0(v0)
11c: R_MIPS_LO16 __osMainEventQueue
120: 00402825 move a1,v0
124: 8fc40018 lw a0,24(s8)
128: 0c000000 jal 0 <osScheduleEvent>
128: R_MIPS_26 __osEnqueueEvent
12c: 00000000 nop
Is there any reason gcc would dereference this pointer? Do I need to reference it with &? (This causes a type mismatch warning so I wouldn't consider this a satisfactory explanation / answer)
There's no pointer dereference. The code is simply loading the value of __osMainEventQueue into $a1 (i.e. the address it points to).
Consider the following scenario: the __osMainEventQueue is located at address 0x12345678 and contains the value 0xDEADBEEF. So what that lui and lw combo does is to first load $v0 with the value 0x12340000. Then it loads from 0x5678($v0), i.e. from (0x12345678), so you end up with 0xDEADBEEF in $v0. Never in this code is there an attempt to read from (0xDEADBEEF).

SV Compilation error: Unexpected token integer

I am compiling the below system verilog code in Active-HDL9.1 simulator. When compile i get this error
Error: VCP2000 tb_hutil.sv : (35, 15): Syntax error. Unexpected token: integer[_INTEGER]. Expected tokens: 'constraint'.
package hutil_pkg;
`define DATE "June_2012"
`ifdef TBID
`else
`define TBID "rapidio2_testbench"
`endif
`ifdef AUTHOR
`else
`define AUTHOR "ALTERA"
`endif
`define INFO 32'h00000001
`define DEBUG 32'h00000002
`define WARNING 32'h00000004
`define FAILURE 32'h00000008
static integer err_cnt; //Line no.35 //error on this line
I don't understand this error and no idea whether the problem is with system verilog syntax or tool issues.
In the posted example an endpackage is missing. Also you could use `ifndef for you if not defined statments.
Example below compiles on EDA Playground:
package hutil_pkg;
`define DATE "June_2012"
`ifndef TBID
`define TBID "rapidio2_testbench"
`endif
`ifndef AUTHOR
`define AUTHOR "ALTERA"
`endif
`define INFO 32'h00000001
`define DEBUG 32'h00000002
`define WARNING 32'h00000004
`define FAILURE 32'h00000008
static integer err_cnt;
endpackage

gcc arm -- ensuring args are retained when inlining functions with inline asm statements

I have a series of functions that are ultimately implemented with an SVC call. For instance:
void func(int arg) {
asm volatile ("svc #123");
}
as you might imagine, the SVC operates on 'arg' which is presumably in a register. if i explictly add a 'noinline' attribute to the definition, everything works as you'd expect.
but, were the function inlined at a higher optimization level, the code that loads 'arg' into a register would be omitted -- as there is apprently no reference to 'arg'.
I've tried adding a 'used' attribute to the declaration of 'arg' itself -- but gcc apparently yields a warning in this case.
I've also tried adding "dummy" asm statements such as
asm ("" : "=r"(arg));
But this didn't appear to work in general. (maybe i need to say volatile here as well???)
Anyway, it seems unfortunate to have an explicit function call for a routine whose body essentially consists of one asm statement.
A relevant recipe is in the GCC manual, in Assembler Instructions with C Expression Operands section, that uses sysint with the same role of your svc instruction. The idea is to define a local register variable with a specified register, and then use extended asmsyntax to add inputs and outputs to the inline assembly block.
I tried to compile the following code:
#include <stdint.h>
__attribute__((always_inline))
uint32_t func(uint32_t arg) {
register uint32_t r0 asm("r0") = arg;
register uint32_t result asm("r0");
asm volatile ("svc #123":"=r" (result) : "0" (r0));
return result;
}
uint32_t foo(void) {
return func(2);
}
This is the disassembly of the compiled (with -O2 flag) object file:
00000000 <func>:
0: ef00007b svc 0x0000007b
4: e12fff1e bx lr
00000008 <foo>:
8: e3a00002 mov r0, #2
c: ef00007b svc 0x0000007b
10: e12fff1e bx lr
func is expanded inline and the argument is put in r0 correctly. I believe volatile is necessary, because if you don't make use of the return value of the service call, then the compiler might assume that the assembly piece of code is not necessary.
You should have a single asm block, compiler is still free to treat two asm blocks individually until otherwise specified. Meaning requirements put on second asm block won't have any effect on the first one.
You are assuming registers will be in their right places because of the calling convention.
What about something like this? (didn't test)
void func(int arg) {
asm volatile (
"mov r0, %[code]\n\t"
"svc #123"
:
: [code]"r" (code)
);
}
For more information, see ARM GCC Inline Assembler Cookbook.

Debugger stops inside mathematical functions that have floating point arguments

I'm using Keil uVision with gcc compiler (Sourcery Codebenchlite for ARM EABI ) to program the STM32F4 cortex M4 chip.
The compiler control strings I have set are:
-march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -std=gnu99 -fsingle-precision-constant
When the debugger encounters some mathematical functions (e.g. asinf(), atan2f() etc), it stops.
I have checked that the arguments for these functions are also single-precision.
I think it is because of some missing compiler directives for the use of VFP floating point, but was unable to identify it.
Is there anything I have missed out?
The disassembly code of an example I did:
The debugger can evaluate atan2f(0.3,0.4), but stops at 0x0803B9CA when it evaluates atan2f(a,b). Didn't know why the number works but not variables.
377: float a = 0.3;
0x0803B9BA 4B1E LDR r3,[pc,#120] ; #0x0803BA34
0x0803B9BC 63BB STR r3,[r7,#0x38]
378: float b = 0.4;
379:
0x0803B9BE 4B1E LDR r3,[pc,#120] ; #0x0803BA38
0x0803B9C0 637B STR r3,[r7,#0x34]
380: float c = atan2f(0.3,0.4);
0x0803B9C2 4B1E LDR r3,[pc,#120] ; #0x0803BA3C
0x0803B9C4 633B STR r3,[r7,#0x30]
381: float d = atan2f(a,b);
382:
0x0803B9C6 6BB8 LDR r0,[r7,#0x38]
0x0803B9C8 6B79 LDR r1,[r7,#0x34]
0x0803B9CA F004F993 BL.W atan2f (0x0803FCF4)
0x0803B9CE 62F8 STR r0,[r7,#0x2C]
On the STM32F4 you first need to enable the FPU - otherwise the CPU will jump into the HardFault_Handler or BusFault_Handler (I'm not shure which one).
You can do it in C/C++ anywhere before you use floating point instructions (maybe at the beginning of main()?). Assuming you use the CMSIS library and have the core_m4.h included (maybe through stm32f4xx.h):
void cortexm4f_enable_fpu() {
/* set CP10 and CP11 Full Access */
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));
}
The alternative is assembler code in the startup file:
/*enable fpu begin*/
ldr r0, =0xe000ed88 /*; enable cp10,cp11 */
ldr r1,[r0]
ldr r2, =0xf00000
orr r1,r1,r2
str r1,[r0]
/*enable fpu end*/
(I found the code somewhere on the internet, don't know where though. I used it myself, it works).
Maybe your problem is located there?

Resources