What is the role of Tick () function is in gem5? - gem5

In many classes, such as CPU, fetch, and decode etc., I see that there is a Tick() function, which is called at the beginning of the simulation. What is the purpose of this function?

Related

Process Instructions storage (Operating System)

I was learning about how a process looks inside a memory from(OS concepts by Abraham silberschatz).
So I came to know that it mainly has following section
HEAP
STACK
DATA/ R/WCode( for global variables)
Text(or ROC) that contains the code
Shared library
OS reserved space
List item
Diagram link
I have some questions regarding the process workflow.
Where does PCB fits in this diagram.
People generally show the called functions getting pushed onto the process stack in memory, but in actual 3 pieces of info gets pushed(local variable, parameters passed and return address).Two sub-questions here:
2.1 Where are the actual instructions stored in this diagram(because stack only has data not instructions). Is it in the text section.
2.2 if this stack data is pushed then they must get popped when the function
execution is completed.So how does Return-Address comes into play while popping.
That "Figure 3.1 - A process in memory", shows the address space of a process.  Each process typically has its own address space (not depicted), and the kernel also typically has its own address space (also not depicted).
The PCBs usually live within the kernel, who is managing the processes.
Functions, when then are not active, still have machine code instructions which are located within the text segment/section of the process.
Functions that are invoked are said to be activated, and an activation record, also known as a stack frame or call frame, is created on the stack for some functions, depending on how complex the function is.  (The stack frame or activation record is effectively private data to the function, not generally intended for other functions to inspect, modulo exception (throw/catch) mechanisms)
A function, X, that calls another function, Y, will suspend itself upon the invocation of Y waiting for Y to return to X, before X resumes.  In such scenario, X uses an activation record on the stack to maintain its suspended state, which it will use upon resumption.
If/when function Y returns to X it must remove any data that it (Y) allocated on the stack, and restore the stack pointer, and other call-preserved registers, to their original value(s) in order for X to successfully resume.  The stack pointer register is the reference for a function to find its stack allocated data.
When X calls Y we can speak to the presence of two return addresses: X has a return address to get back to its caller, and Y has a return address to get back to X.  As this is the nature of calling, some architectures will provide instructions for calling that also push the return address directly onto the stack, and provide instructions for returning that pop the return address off the stack to resume the caller.
However, RISC architectures will generally leave the return address in a CPU register, requiring functions that make further calls to save their own return address in a place that will survive their own further calling (that place being stack memory).  RISC architectures also tend to engage in less pushing and popping, collecting all stack frame allocations into one (larger) allocation in prologue and all stack frame deallocations into one (larger) deallocation in epilogue.
The suspension, invocation, returning, and resumption is logical, from the point of view of functions: though the processor doesn't really see or care about functions, but rather instead sees a continuous stream of instructions that happen to include various forms of branching.

whats the relation between ISR and callback function?

I am a little confused about ISR and callback function.
I just know the ISR have no input params and return value. But i use TI MCU SDK register a timer params containing callback function with input params. I want to know how does this timer ISR run the callback function? What is the actual flow CPU runs?
An interrupt (service routine) is called by hardware. A callback function is called by software, which could be a driver, OS or library.
Some libs or drivers might be designed so that you pass along a function pointer to a custom function. Then the driver implements the ISR so that the ISR calls your callback. This provides an abstraction layer at the expensive of some extra function call overhead.
I don't know how your TI driver is implemented, but it is common to have a timer driver register a list of callbacks with corresponding timeouts, then inside the ISR run a loop and check if it is time to execute a certain callback. With such designs it's important to keep the callback functions small.
As answered the hardware for a specific chip or architecture has a very specific way that interrupts are handled. A fixed address where the first instruction for a specific handler is or a fixed address where the address to the handler lives.
Then you add to this the mcu company wants to make your experience easier and tries to do much of the work for you. So they may have a generic handler for each thing and a library system where you tell their library where your code is, their software then has some, likely ram based scheme, if your handler is registered runtime, that is used by the real handler to branch/jump/call yours.
In this case the actual ISR would be TI code.
If you, in your code, have indicated you want to "handle" the interrupt then via library calls or some other scheme you indicate the interrupt you want to handle and the function you want to be called (and sure, perhaps even parameters can be part of this design scheme). This call to indicate your callback function likely also enables that interrupt into the cpu. Depending on the architecture there may be one big handler and only one interrupt or hundreds of individual interrupts and possibly a handler for each, or somewhere in the middle. So it may enable an individual interrupt or it may just enable an if-then-else path in some code the mcu vendor wrote.
interrupt comes into the cpu
cpu finds a good stopping point (between instructions usually)
cpu specific solution for finding the interrupt service routine code, either hardcoded address or hardcoded address in a vector table, or a way to register an address in the logic.
No generally you do not have parameters passed to the real isr. The isr will need to know what caused the interrupt and this is very much processor architecture specific. It is generally not "passed" to the handler like a compiled function call, instead control and status registers are often used.
In this scheme ti writes the isr, but then in some part of their software design they then call your function as if it were a normal compiled function. Possibly even with parameters depending on their design scheme.
Your function eventually finishes and returns
The ti isr finishes and indicates to the processor to continue with the code that was interrupted.

How to best convert legacy polling embedded firmware architecture into an event driven one?

I've got a family of embedded products running a typical main-loop based firmware with 150+k lines of code. A load of complex timing critical features is realized by a combination of hardware interrupt handlers, timer polling and protothreads (think co-routines). Actually protothreads are polling well and "only" are syntactic sugar to mimic pseudo-parallel scheduling of multiple threads (endless loops). I add bugfixes and extensions to the firmware all the time. There are about 30k devices of about 7 slightly different hardware types and versions out in the field.
For a new product-family member I need to integrate an external FreeRTOS-based project on the new product only while all older products need to get further features and improvements.
In order to not have to port the whole complex legacy firmware to FreeRTOS with all the risk of breaking perfectly fine products I plan to let the old firmware run inside a FreeRTOS task. On the older products the firmware shall still not run without FreeRTOS. Inside the FreeRTOS task the legacy firmware would consume all available processor time because its underlying implementation scheme is polling based. Due to the fact that its using prothreads (timer and hardware polling based behind the scenes) and polls on a free-running processor counter register I hope that I can convert the polling into a event driven behavior.
Here are two examples:
// first example: do something every 100 ms
if (GET_TICK_COUNT() - start > MS(100))
{
start = GET_TICK_COUNT();
// do something every 100 ms
}
// second example: wait for hardware event
setup_hardware();
PT_WAIT_UNTIL(hardware_ready(), pt);
// hardware is ready, do something else
So I got the impression that I can convert these 2 programming patterns (e.g. through macro magic and FreeRTOS functionality) into an underlying event based scheme.
So now my question: has anybody done such a thing already? Are there patterns and or best practices to follow?
[Update]
Thanks for the detailed responses. Let me comment some details: My need is to combine a "multithreading-simulation based legacy firmware (using coo-routines implementation protothreads)" and a FreeRTOS based project being composed of a couple of interacting FreeRTOS tasks. The idea is to let the complete old firmware run in its own RTOS task besides the other new tasks. I'm aware of RTOS principles and patterns (pre-emption, ressource sharing, blocking operations, signals, semaphores, mutexes, mailboxes, task priorities and so forth). I've planed to base the interaction of old and new parts exactly on these mechanisms. What I'm asking for is 1) Ideas how to convert the legacy firmware (150k+ LOC) in a semi-automated way so that the busy-waiting / polling schemes I presented above are using either the new mechanisms when run inside the RTOS tasks or just work the old way when build and run as the current main-loop-kind of firmware. A complete rewrite / full port of the legacy code is no option. 2) More ideas how to teach the old firmware implementation that is used to have full CPU resources on its hands to behave nicely inside its new prison of a RTOS task and not just consume all CPU cycles available (when given the highest priority) or producing new large Real Time Latencies when run not at the highest RTOS priority.
I guess here is nobody who already has done such a very special tas. So I just have to do the hard work and solve all the described issues one after another.
In an RTOS you create and run tasks. If you are not running more than one task, then there is little advantage in using an RTOS.
I don't use FreeRTOS (but have done), but the following applies to any RTOS, and is pseudo-code rather then FreeRTOS API specific - many details such as task priorities and stack allocation are deliberately missing.
First in most simple RTOS, including FreeRTOS, main() is used for hardware initialisation, task creation, and scheduler start:
int main( void )
{
// Necessary h/w & kernel initialisation
initHardware() ;
initKernel() ;
// Create tasks
createTask( task1 ) ;
createTask( task2 ) ;
// Start scheduling
schedulerStart() ;
// schedulerStart should not normally return
return 0 ;
}
Now let us assume that your first example is implemented in task1. A typical RTOS will have both timer and delay functions. The simplest to use is a delay, and this is suitable when the periodic processing is guaranteed to take less than one OS tick period:
void task1()
{
// do something every 100 ms
for(;;)
{
delay( 100 ) ; // assuming 1ms tick period
// something
...
}
}
If the something takes more than 1ms in this case, it will not be executed every 100ms, but 100ms plus the something execution time, which may itself be variable or non-deterministic leading to undesirable timing jitter. In that case you should use a timer:
void task1()
{
// do something every 100 ms
TIMER timer = createTimer( 100 ) ; // assuming 1ms tick period
for(;;)
{
timerWait() ;
// something
...
}
}
That way something can take up to 100ms and will still be executed accurately and deterministically every 100ms.
Now to your second example; that is a little more complex. If nothing useful can happen until the hardware is initialised, then you may as well use your existing pattern in main() before starting the scheduler. However as a generalisation, waiting for something in a different context (task or interrupt) to occur is done using a synchronisation primitive such as a semaphore or task event flag (not all RTOS have task event flags). So in a simple case in main() you might create a semaphore:
createSemaphore( hardware_ready ) ;
Then in the context performing the process that must complete:
// Init hardware
...
// Tell waiting task hardware ready
semaphoreGive( hardware_ready ) ;
Then in some task that will wait for the hardware to be ready:
void task2()
{
// wait for hardware ready
semaphoreTake( hardware_ready ) ;
// do something else
for(;;)
{
// This loop must block is any lower-priority task
// will run. Equal priority tasks may run is round-robin
// scheduling is implemented.
...
}
}
You are facing two big gotchas...
Since the old code is implemented using protothreads (coroutines), there is never any asynchronous resource contention between them. If you split these into FreeRTOS tasks, there there will be preemptive scheduling task switches; these switches may occur at places where the protothreads were not expecting, leaving data or other resources in an inconsistent state.
If you convert any of your protothreads' PT_WAIT calls into real waits in FreeRTOS, the call will really block. But the protothreads assume that other protothreads continue while they're blocked.
So, #1 implies you cannot just convert protothreads to tasks, and #2 implies you must convert protothreads to tasks (if you use FreeRTOS blocking primitives, like xEventGroupWaitBits().
The most straightforward approach will be to put all your protothreads in one task, and continue polling within that task.

Timed simulation with SystemC

With reference to question SystemC module not working with SC_THREAD, a timed simulation is imitated using next_trigger(). As I understood from this article, this restarts the thread after the specified time:
next_trigger(double, sc_time_unit): The process shall be triggered when specified time has elapsed.
I.e. it effectively executes the operations after the occurrence of this instruction after the time specified, but also executes the operations found before that instruction. I have the feeling that the repeated utilization of next_trigger within an SC_THREAD may result in 'glitches' in the simulation.
Q1: Is my feeling correct?
Q2: Is there another possibility to delay execution (something that suspending the thread for the given time, rather than restarting it)
First of all next_trigger can only be used with SC_METHOD's as mentioned here:
next_trigger() is used with process methods, one's which are not threads.
Here are a few pointer's in term of SystemC processes:
SC_METHOD's are processes which must complete it's execution at one pass.(e.g.: a simple function call)
Note: Do not use while(1) loops in SC_METHOD's.
SC_THREAD's are processes which are separate thread of execution, one must explicitly use wait() statements here to synchronize the SystemC kernel simulation. This is the place where you will mostly find while(1) (infinite) loops in use.
For suspending the thread for some simulation time you can use the wait() statement to introduce the perceived delay.
But for better understanding you need to understand the difference between static and dynamic sensitivity in SystemC refer here for more information.

ATtiny85: how to respond simultaneously to pin and timer interrupts

I've recently been playing around with the ATtiny85 as a means of prototyping some simple electronics in a very small package. I'm having a spot of trouble with this since the language used for many of its functions is very different (and a lot less intuitive!) than that found in a standard Arduino sketch. I'm having some difficulty finding a decent reference for the hardware-specific functions too.
Primarily, what I'd like to do is listen for both a pin change and a timer at the same time. A change of state in the pin will reset the timer, but at the same time the code needs to respond to the timer itself if it ends before the pin's state changes.
Now, from the tutorials I've managed to find it seems that both pin change and timer interrupts are funnelled through the same function - ISR(). What I'd like to know is:
Is it possible to have both a pin and a timer interrupt going at the same time?
Assuming they both call the same function, how do you tell them apart?
ISR() is not a function, it's a construct (macro) that is used to generate the stub for an ISR as well as inject the ISR into the vector table. The vector name passed to the macro determines which interrupt it services.
ISR(INT0_vect)
{
// Handle external interrupt 0 (PB2)
...
};
ISR(TIM0_OVF_vect)
{
// Handle timer 0 overflow
...
};
According to the datasheet ATtiny85 doesn't have the same interrupt vector for PCINT0 and TIMER1 COMPA/OVF/COMPB, so you can define different ISR handlers for each one of them.
If you're using the same handler for more interrupts, it might be impossible to differentiate between them, as interrupt flags are usually cleared by hardware on ISR vector execution.
As an addition to the accepted answer:
Is it possible to have both a pin and a timer interrupt going at the same time?
The interrupt can occur at exactly the same time on the hardware level and the corresponding interrupt flags would be set accordingly. The flags indicate that the ISR for the respective interrupt should be executed. But the actual ISRs are (more or less obviously) not executed at the same time / in parallel. Which ISR is executed first (in case multiple interrupts are pending) depends on the interrupt priority, which is specified in the interrupt vector table from the data sheet.