/*
 * core.h - core descriptor and associated access functions définition
 *
 * Authors  Ghassan Almaless (2008,2009,2010,2011,2012)
 *          Alain Greiner (2016,2017,2018)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _CORE_H_
#define _CORE_H_

#include <kernel_config.h>
#include <hal_kernel_types.h>
#include <busylock.h>
#include <list.h>
#include <rpc.h>
#include <scheduler.h>

/****  Forward declarations  ****/

struct thread_s;
struct chdev_s;

/****************************************************************************************
 * This structure defines a core descriptor.
 * Besides the core identifiers (gid,lid), it contains an embedded private scheduler
 * and a software cycles counter on 64 bits.
 * It contains also the root of local list of alarms, dynamically registered by the
 * threads running on this core. This local list is protected by a remote_busylock,
 * because it can be accessed by any thread, running in any cluster, and using the
 * access functions defined in the <alarm.c> & <alarm.h> files. 
 * It contains an architecture specific extension to store the interrupt vector(s).
 * The core_init()function must allocate memory for this extension, depending on the
 * PIC device implementation type.
 ***************************************************************************************/

typedef struct core_s
{
	lid_t               lid;            /*! core local index in cluster                */
	gid_t               gid;            /*! core global identifier (hardware index)    */

	scheduler_t         scheduler;      /*! embedded private scheduler                 */

	uint64_t            cycles;         /*! total number of cycles (from hard reset)   */
	uint32_t            time_stamp;     /*! previous time stamp (read from register)   */

    list_entry_t        alarms_root;    /*! root of list of attached alarms            */
    remote_busylock_t   alarms_lock;    /*! lock protecting the list of alarms         */

	uint32_t            ticks_nr;       /*! number of elapsed ticks                    */
	uint32_t            usage;          /*! cumulated busy_percent (idle / total)      */
	struct thread_s   * fpu_owner;      /*! pointer on current FPU owner thread        */
    uint32_t            rand_last;      /*! last computed random value                 */

    void              * pic_extend;     /*! PIC implementation specific extension      */
}
core_t;

/***************************************************************************************
 * This function initializes a core descriptor.
 * It makes the association [gid] <=> [lid], as defined in arch_info, via the
 * boot_info_t structure build by the bootloader in each cluster.
 * It initializes the core scheduler structures, and the alarms list and lock.
 * It allocates memory for the PIC infrastructure specific core extension,
 * but it does NOT initialize the <pic_extend> fields, that must be completed later.
 ***************************************************************************************
 * @ core      : pointer on core descriptor to initialise.
 * @ lid       : local core index in cluster.
 * @ gid       : global core identifier (hardware index).
 **************************************************************************************/
void core_init( core_t          * core,
                lid_t             lid,
                gid_t             gid );

/***************************************************************************************
 * This function returns the calling core local index (lid), making an associative
 * search in the local core_tbl[] array, based on the hardwired (gid).
 ***************************************************************************************
 * @ returns always the lid value.
 **************************************************************************************/
lid_t core_lid( void );

/***************************************************************************************
 * This function returns a pseudo random number from the core descriptor
 * private random generator.
 ***************************************************************************************
 * @ core       : pointer on core descriptor.
 * @ returns the pseudo random value.
 **************************************************************************************/
inline uint32_t core_get_rand( core_t * core );

/***************************************************************************************
 * This function returns the current date (seconds & micro-seconds) from 
 * the 64 bits calling core cycles counter.
 ***************************************************************************************
 * @ core      : pointer on core descriptor.
 * @ tm_s      : number of seconds.
 * @ tm_us     : number of micro-seconds.
 **************************************************************************************/
void core_get_time( core_t   * core,
                    uint32_t * tm_s,
                    uint32_t * tm_us );

/***************************************************************************************
 * This function must be called at each TICK.
 * - it updates the ticks counter in the calling core descriptor.
 * - it checks the registered alarms depending on the ticks counter value.
 * - it calls the scheduler, depending on the ticks counter value.
 ***************************************************************************************
 * @ core       : pointer on core descriptor.
 **************************************************************************************/
void core_clock( core_t * core );

/***************************************************************************************
 * This function updates the usage statistics for the calling core descriptor,
 * based on the ratio between the idle_ticks and total_ticks.
 ***************************************************************************************
 * @ core       : pointer on core descriptor.
 **************************************************************************************/
void core_compute_stats( core_t * core );

/***************************************************************************************
 * This function reset the usage statistics.
 ***************************************************************************************
 * @ core       : pointer on core descriptor.
 **************************************************************************************/
void core_reset_stats( core_t * core );

/***************************************************************************************
 * This function set/reset a selected entry in one interrupt vector for a remote core.
 * The written value is an extended pointer on the "source" device (or the XPTR_NULL
 * value in case of reset). As it uses remote access, this function can be called by
 * any thread in any cluster.
 ***************************************************************************************
 * @ core       : local pointer on the core descriptor.
 * @ irq_type   : type of IRQ (HWI/WTI/PTI).
 * @ irq_id     : index in the IRQ vector.
 * @ chdev      : local pointer on the "source" chdev descriptor.
 **************************************************************************************/
void core_set_irq_vector_entry( core_t          * core,
                                uint32_t          irq_type,
                                uint32_t          irq_id,
                                struct chdev_s  * chdev );


#endif	/* _CORE_H_ */
