//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name:   WrtdTstamp
//
// description: A collection of definitions and types used by the WrtdDev class.
//
// These are mostly copy-pasted from the WRTD library.
//
//------------------------------------------------------------------------------
// Copyright CERN 2019
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------

`ifndef __WRTD_DEFINE_INCLUDED
 `define __WRTD_DEFINE_INCLUDED

 `include "simdrv_defs.svh"

 `define WRTD_MAX_CPUS 4
 `define WRTD_MAX_DEVS 4

 `define WRTD_ID_LEN 16

 `define WRTD_IO_MSG_WORD_SIZE  2
 `define WRTD_CFG_MSG_WORD_SIZE 5
 `define WRTD_ROOT_WORD_SIZE    13
 `define WRTD_RULE_WORD_SIZE    43
 `define WRTD_ALRM_WORD_SIZE    15

 `define WRTD_DEST_CPU_LOCAL 'hfe
 `define WRTD_DEST_CH_NET    'hff

 `define WRTD_CAP_NET_RX   1
 `define WRTD_CAP_NET_TX   2
 `define WRTD_CAP_LOCAL_RX 4
 `define WRTD_CAP_LOCAL_TX 8

enum {
      WRTD_ACTION_GET_CONFIG,
      WRTD_ACTION_READW,
      WRTD_ACTION_WRITEW
} wrtd_trtl_actions;

 `define WRTD_ACTION_LOG 'h20

typedef enum uint32_t {
      WRTD_LOG_MSG_EV_NONE = 0,
      WRTD_LOG_MSG_EV_GENERATED,
      WRTD_LOG_MSG_EV_CONSUMED,
      WRTD_LOG_MSG_EV_DISCARDED,
      WRTD_LOG_MSG_EV_NETWORK
} wrtd_log_msg_type;

typedef enum uint32_t {
      WRTD_LOG_GENERATED_ALARM    = 1,
      WRTD_LOG_GENERATED_DEVICE_0 = 8,
      WRTD_LOG_GENERATED_DEVICE_1 = 16,
      WRTD_LOG_GENERATED_DEVICE_2 = 24,
      WRTD_LOG_GENERATED_DEVICE_3 = 32,
      WRTD_LOG_GENERATED_DEVICE_4 = 40,
      WRTD_LOG_GENERATED_DEVICE_5 = 48,
      WRTD_LOG_GENERATED_DEVICE_6 = 56,
      WRTD_LOG_GENERATED_DEVICE_7 = 64
} wrtd_log_gen_reason;

typedef enum uint32_t {
      WRTD_LOG_CONSUMED_START = 1,
      WRTD_LOG_CONSUMED_DONE
} wrtd_log_con_reason;

typedef enum uint32_t {
      WRTD_LOG_DISCARD_NO_SYNC = 1,
      WRTD_LOG_DISCARD_HOLDOFF,
      WRTD_LOG_DISCARD_TIMEOUT,
      WRTD_LOG_DISCARD_OVERFLOW
} wrtd_log_dsc_reason;

typedef enum uint32_t {
      WRTD_LOG_NETWORK_TX = 1,
      WRTD_LOG_NETWORK_RX
} wrtd_log_net_reason;

enum {
      WRTD_DIR_INPUT,
      WRTD_DIR_OUTPUT
} wrtd_dir;

typedef uint32_t wrtd_data[];

function int wrtd_gen_hash ( string s );
   return ( s[0] ^ s[3] ^ s[4] ^ s[7] );
endfunction // wrtd_gen_hash

class WrtdTstamp;
   protected string   name;
   protected uint32_t seconds;
   protected uint32_t ns;
   protected uint32_t frac;

   function new ( uint32_t seconds = 0,
                  uint32_t ns      = 0,
                  uint32_t frac    = 0 );
      set ( seconds, ns, frac );
   endfunction // new

   function void set ( uint32_t seconds, uint32_t ns, uint32_t frac );
      this.seconds = seconds;
      this.ns      = ns;
      this.frac    = frac;
   endfunction // set

   function uint32_t get_sec ( );
      return this.seconds;
   endfunction // get_sec

   function uint32_t get_ns ( );
      return this.ns;
   endfunction // get_ns

   function uint32_t get_frac ( );
      return this.frac;
   endfunction // get_frac

   function wrtd_data data_pack ( );
      wrtd_data ret=new[3];
      ret[0] = this.seconds;
      ret[1] = this.ns;
      ret[2] = this.frac;
      return ret;
   endfunction // data_pack

   function void data_unpack ( wrtd_data data);
      this.seconds = data[0];
      this.ns      = data[1];
      this.frac    = data[2];
   endfunction // data_unpack

   function void zero ( );
      set ( 0, 0, 0 );
   endfunction // zero

   function string tostring ( );
      return $sformatf ( "%0d:%0d.%0d", this.seconds, this.ns, this.frac );
   endfunction; // tostring

endclass // WrtdTstamp

class WrtdId;

   protected string id;

   function new ();
      clear();
   endfunction // new

   function void clear ();
      id = "";
   endfunction // clear

   function void set ( string id );
      if ( id.len() > `WRTD_ID_LEN )
        $error ( "length of string longer than the available storage" );
      else
        begin
           this.clear();
           this.id = id;
        end
   endfunction // set

   function string get ( );
      return this.id;
   endfunction // get

   function wrtd_data data_pack ( );
      int i;
      wrtd_data d;
      d = new[`WRTD_ID_LEN / 4];
      for ( i = 0; i < `WRTD_ID_LEN / 4; i ++ )
        d[i] = 0;
      for ( i = 0; i < this.id.len(); i ++ )
        d[i/4] |= this.id[i] << ( 8 * ( i % 4 ) );
      return d;
   endfunction // data_pack

   function void data_unpack ( wrtd_data data );
      if ( data.size() > `WRTD_ID_LEN / 4 )
        $error ( "length of data longer than the available storage" );
      else
        this.id = { <<32 { { <<8 { data } } } };
   endfunction // data_unpack

   function int is_empty ( );
      return ( this.id.len() == 0 );
   endfunction // is_empty

endclass // WrtdId

typedef struct {
   WrtdTstamp ts;
   WrtdId     id;
   uint32_t   seq;
   byte unsigned flags;
} wrtd_event;

typedef struct {
   uint32_t addr;
   WrtdId fw_name;
   uint32_t fw_id;
   uint32_t nbr_alarms;
   uint32_t alarms_addr;
   uint32_t nbr_rules;
   uint32_t capabilities;
   uint32_t rules_addr;
   uint32_t nbr_devs;
   uint32_t nbr_channels[4];
   uint32_t channel_dir[4];
} wrtd_root;

`endif //  `ifndef __WRTD_DEFINE_INCLUDED
