{% from "_helpers.j2" import safe_attr %}
{{ header | safe }}

`default_nettype none

module power_transitions #(
    parameter NUM_STATES = 8
) (
    input  wire  clk,
    input  wire  rst_n,
    
    // State inputs
    input  wire  [2:0] current_state,
    input  wire  [2:0] next_state,
    
    // Transition outputs
    output logic [15:0] transition_counter,
    output logic transition_complete,
    output logic transition_in_progress,
    output logic [7:0] transition_progress_percent,
    output logic power_domain_enable,
    output logic aux_power_enable
);

// Power Transition Logic
logic [2:0] transition_source_state;
logic [2:0] transition_target_state;

// Transition delay lookup
// Use safe accessor for transition delays (fall back to top-level transition_delays)
{%- set _td_candidate = safe_attr(config, 'transition_delays', transition_delays | default({})) -%}
{%- if _td_candidate is mapping -%}
{%- set _td = _td_candidate -%}
{%- elif _td_candidate is sequence -%}
{%- set _td = _td_candidate -%}
{%- else -%}
{%- set _td = {} -%}
{%- endif -%}
function automatic [15:0] get_transition_delay(logic [2:0] from_state, logic [2:0] to_state);
    case ({from_state, to_state})
        {% if _td is mapping %}
            {% for pair, delay in _td.items() %}
                {3'd{{ loop.index0 }}, 3'd{{ loop.index0 + 1 }}}: return 16'd{{ delay }};
            {% endfor %}
        {% elif _td is sequence %}
            {% for pair in _td %}
                {3'd{{ loop.index0 }}, 3'd{{ loop.index0 + 1 }}}: return 16'd{{ pair[2] if pair|length > 2 else pair[2-1] if pair|length>1 else 100 }};
            {% endfor %}
        {% endif %}
        default: return 16'd100; // Default transition delay
    endcase
endfunction

// Transition state machine
always_ff @(posedge clk or negedge rst_n) begin
    // Hoist declarations to the top of the block for tool compatibility
    logic [15:0] required_delay;
    if (!rst_n) begin
        transition_counter <= 16'h0;
        transition_complete <= 1'b0;
        transition_in_progress <= 1'b0;
        transition_source_state <= 3'h0;
        transition_target_state <= 3'h0;
    end else begin
        if (current_state != next_state && !transition_in_progress) begin
            // Start new transition
            transition_counter <= 16'h0;
            transition_complete <= 1'b0;
            transition_in_progress <= 1'b1;
            transition_source_state <= current_state;
            transition_target_state <= next_state;
        end else if (transition_in_progress) begin
            required_delay = get_transition_delay(transition_source_state, transition_target_state);
            
            if (transition_counter < required_delay) begin
                transition_counter <= transition_counter + 1'b1;
                transition_complete <= 1'b0;
            end else begin
                transition_counter <= 16'h0;
                transition_complete <= 1'b1;
                transition_in_progress <= 1'b0;
            end
        end else begin
            transition_complete <= 1'b0;
        end
    end
end

// Transition progress indicator (for debugging/monitoring)
logic [7:0] transition_progress_percent;
always_comb begin
    // Declare locals at top of block
    logic [15:0] required_delay;
    if (transition_in_progress) begin
        required_delay = get_transition_delay(transition_source_state, transition_target_state);
        if (required_delay > 0) begin
            transition_progress_percent = (transition_counter * 8'd100) / required_delay;
        end else begin
            transition_progress_percent = 8'd100;
        end
    end else begin
        transition_progress_percent = 8'd0;
    end
end

// Power domain control signals during transitions
always_comb begin
    case ({transition_source_state, transition_target_state})
        {% if _td is mapping %}
            {% for pair, delay in _td.items() %}
                {3'd{{ loop.index0 }}, 3'd{{ loop.index0 + 1 }}}: begin
                    {% set from_state = pair[0] if pair is sequence else pair[0] %}
                    {% set to_state = pair[1] if pair is sequence else pair[1] %}
                    {%- if from_state is mapping -%}
                        {%- set from_state_value = from_state.get('value', from_state.get('name', 'D0')) -%}
                    {%- elif from_state is string -%}
                        {%- set from_state_value = from_state -%}
                    {%- else -%}
                        {%- set from_state_value = (from_state|string) -%}
                    {%- endif -%}
                    {%- if to_state is mapping -%}
                        {%- set to_state_value = to_state.get('value', to_state.get('name', 'D0')) -%}
                    {%- elif to_state is string -%}
                        {%- set to_state_value = to_state -%}
                    {%- else -%}
                        {%- set to_state_value = (to_state|string) -%}
                    {%- endif -%}
                    {% if from_state_value == "D0" and to_state_value == "D3_HOT" -%}
                        power_domain_enable = transition_complete ? 1'b0 : 1'b1;
                        aux_power_enable = 1'b1;
                    {% elif from_state_value == "D3_HOT" and to_state_value == "D0" -%}
                        power_domain_enable = transition_complete ? 1'b1 : 1'b0;
                        aux_power_enable = 1'b1;
                    {% else -%}
                        power_domain_enable = 1'b1;
                        aux_power_enable = 1'b1;
                    {% endif %}
                end
            {% endfor %}
        {% elif _td is sequence %}
            {% for pair in _td %}
                {3'd{{ loop.index0 }}, 3'd{{ loop.index0 + 1 }}}: begin
                    {% set from_state = pair[0] if pair|length>0 else 'D0' %}
                    {% set to_state = pair[1] if pair|length>1 else 'D0' %}
                    {%- if from_state is mapping -%}
                        {%- set from_state_value = from_state.get('value', from_state.get('name', 'D0')) -%}
                    {%- elif from_state is string -%}
                        {%- set from_state_value = from_state -%}
                    {%- else -%}
                        {%- set from_state_value = (from_state|string) -%}
                    {%- endif -%}
                    {%- if to_state is mapping -%}
                        {%- set to_state_value = to_state.get('value', to_state.get('name', 'D0')) -%}
                    {%- elif to_state is string -%}
                        {%- set to_state_value = to_state -%}
                    {%- else -%}
                        {%- set to_state_value = (to_state|string) -%}
                    {%- endif -%}
                    {% if from_state_value == "D0" and to_state_value == "D3_HOT" -%}
                        power_domain_enable = transition_complete ? 1'b0 : 1'b1;
                        aux_power_enable = 1'b1;
                    {% elif from_state_value == "D3_HOT" and to_state_value == "D0" -%}
                        power_domain_enable = transition_complete ? 1'b1 : 1'b0;
                        aux_power_enable = 1'b1;
                    {% else -%}
                        power_domain_enable = 1'b1;
                        aux_power_enable = 1'b1;
                    {% endif %}
                end
            {% endfor %}
        {% endif %}
        default: begin
            power_domain_enable = 1'b1;
            aux_power_enable = 1'b1;
        end
    endcase
end

endmodule

`default_nettype wire
