aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog/verilog_frontend.h
blob: a7c9b2fe6ab71303f037d7c0ee5dfb2896766d76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *  ---
 *
 *  The Verilog frontend.
 *
 *  This frontend is using the AST frontend library (see frontends/ast/).
 *  Thus this frontend does not generate RTLIL code directly but creates an
 *  AST directly from the Verilog parse tree and then passes this AST to
 *  the AST frontend library.
 *
 */

#ifndef VERILOG_FRONTEND_H
#define VERILOG_FRONTEND_H

#include "kernel/yosys.h"
#include "frontends/ast/ast.h"
#include <stdio.h>
#include <stdint.h>
#include <list>

YOSYS_NAMESPACE_BEGIN

namespace VERILOG_FRONTEND
{
	// this variable is set to a new AST_DESIGN node and then filled with the AST by the bison parser
	extern struct AST::AstNode *current_ast;

	// this function converts a Verilog constant to an AST_CONSTANT node
	AST::AstNode *const2ast(std::string code, char case_type = 0, bool warn_z = false);

	// state of `default_nettype
	extern bool default_nettype_wire;

	// running in SystemVerilog mode
	extern bool sv_mode;

	// running in -formal mode
	extern bool formal_mode;

	// running in -noassert mode
	extern bool noassert_mode;

	// running in -noassume mode
	extern bool noassume_mode;

	// running in -norestrict mode
	extern bool norestrict_mode;

	// running in -assume-asserts mode
	extern bool assume_asserts_mode;

	// running in -assert-assumes mode
	extern bool assert_assumes_mode;

	// running in -lib mode
	extern bool lib_mode;

	// running in -specify mode
	extern bool specify_mode;

	// lexer input stream
	extern std::istream *lexin;
}

// the pre-processor
std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map<std::string, std::string> &pre_defines_map,
		dict<std::string, std::pair<std::string, bool>> &global_defines_cache, const std::list<std::string> &include_dirs);

YOSYS_NAMESPACE_END

// the usual bison/flex stuff
extern int frontend_verilog_yydebug;
int frontend_verilog_yylex(void);
void frontend_verilog_yyerror(char const *fmt, ...);
void frontend_verilog_yyrestart(FILE *f);
int frontend_verilog_yyparse(void);
int frontend_verilog_yylex_destroy(void);
int frontend_verilog_yyget_lineno(void);
void frontend_verilog_yyset_lineno (int);

#endif
ground-color: #ffffc0; padding: 0 5px 0 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# Copyright 2017 Fred Sundvik
#
# This program 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, either version 2 of the License, or
# (at your option) any later version.
#
# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.

SERIAL_DIR := $(QUANTUM_DIR)/serial_link
SERIAL_PATH := $(QUANTUM_PATH)/serial_link
SERIAL_SRC := $(wildcard $(SERIAL_PATH)/protocol/*.c)
SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c)
SERIAL_DEFS += -DSERIAL_LINK_ENABLE
COMMON_VPATH += $(SERIAL_PATH)

ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
    OPT_DEFS += -DAPI_SYSEX_ENABLE
    SRC += $(QUANTUM_DIR)/api/api_sysex.c
    OPT_DEFS += -DAPI_ENABLE
    SRC += $(QUANTUM_DIR)/api.c
    MIDI_ENABLE=yes
endif

MUSIC_ENABLE := 0

ifeq ($(strip $(AUDIO_ENABLE)), yes)
    OPT_DEFS += -DAUDIO_ENABLE
    MUSIC_ENABLE := 1
    SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c
    SRC += $(QUANTUM_DIR)/process_keycode/process_clicky.c
    ifeq ($(PLATFORM),AVR)
        SRC += $(QUANTUM_DIR)/audio/audio.c
    else
        SRC += $(QUANTUM_DIR)/audio/audio_arm.c
    endif
    SRC += $(QUANTUM_DIR)/audio/voices.c
    SRC += $(QUANTUM_DIR)/audio/luts.c
endif

ifeq ($(strip $(MIDI_ENABLE)), yes)
    OPT_DEFS += -DMIDI_ENABLE
    MUSIC_ENABLE := 1
    SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
endif

ifeq ($(MUSIC_ENABLE), 1)
    SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
endif

ifeq ($(strip $(COMBO_ENABLE)), yes)
    OPT_DEFS += -DCOMBO_ENABLE
    SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c
endif

ifeq ($(strip $(STENO_ENABLE)), yes)
    OPT_DEFS += -DSTENO_ENABLE
    VIRTSER_ENABLE ?= yes
    SRC += $(QUANTUM_DIR)/process_keycode/process_steno.c
endif

ifeq ($(strip $(VIRTSER_ENABLE)), yes)
    OPT_DEFS += -DVIRTSER_ENABLE
endif

ifeq ($(strip $(FAUXCLICKY_ENABLE)), yes)
    OPT_DEFS += -DFAUXCLICKY_ENABLE
    SRC += $(QUANTUM_DIR)/fauxclicky.c
endif

ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
    OPT_DEFS += -DPOINTING_DEVICE_ENABLE
    OPT_DEFS += -DMOUSE_ENABLE
    SRC += $(QUANTUM_DIR)/pointing_device.c
endif

ifeq ($(strip $(UCIS_ENABLE)), yes)
    OPT_DEFS += -DUCIS_ENABLE
    UNICODE_COMMON := yes
    SRC += $(QUANTUM_DIR)/process_keycode/process_ucis.c
endif

ifeq ($(strip $(UNICODEMAP_ENABLE)), yes)
    OPT_DEFS += -DUNICODEMAP_ENABLE
    UNICODE_COMMON := yes
    SRC += $(QUANTUM_DIR)/process_keycode/process_unicodemap.c
endif

ifeq ($(strip $(UNICODE_ENABLE)), yes)
    OPT_DEFS += -DUNICODE_ENABLE
    UNICODE_COMMON := yes
    SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c
endif

ifeq ($(strip $(UNICODE_COMMON)), yes)
    SRC += $(QUANTUM_DIR)/process_keycode/process_unicode_common.c
endif

VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c
EEPROM_DRIVER ?= vendor
ifeq ($(filter $(EEPROM_DRIVER),$(VALID_EEPROM_DRIVER_TYPES)),)
  $(error EEPROM_DRIVER="$(EEPROM_DRIVER)" is not a valid EEPROM driver)
else
  OPT_DEFS += -DEEPROM_ENABLE
  ifeq ($(strip $(EEPROM_DRIVER)), custom)
    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_CUSTOM
    COMMON_VPATH += $(DRIVER_PATH)/eeprom
    SRC += eeprom_driver.c
  else ifeq ($(strip $(EEPROM_DRIVER)), i2c)
    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_I2C
    COMMON_VPATH += $(DRIVER_PATH)/eeprom
    QUANTUM_LIB_SRC += i2c_master.c
    SRC += eeprom_driver.c eeprom_i2c.c
  else ifeq ($(strip $(EEPROM_DRIVER)), transient)
    OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_TRANSIENT
    COMMON_VPATH += $(DRIVER_PATH)/eeprom
    SRC += eeprom_driver.c eeprom_transient.c
  else ifeq ($(strip $(EEPROM_DRIVER)), vendor)
    OPT_DEFS += -DEEPROM_VENDOR
    ifeq ($(PLATFORM),AVR)
      # Automatically provided by avr-libc, nothing required
    else ifeq ($(PLATFORM),CHIBIOS)
      ifeq ($(MCU_SERIES), STM32F3xx)
        SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
        SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
        OPT_DEFS += -DEEPROM_EMU_STM32F303xC
        OPT_DEFS += -DSTM32_EEPROM_ENABLE
      else ifeq ($(MCU_SERIES), STM32F1xx)
        SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
        SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
        OPT_DEFS += -DEEPROM_EMU_STM32F103xB
        OPT_DEFS += -DSTM32_EEPROM_ENABLE
      else ifeq ($(MCU_SERIES)_$(MCU_LDSCRIPT), STM32F0xx_STM32F072xB)
        SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
        SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
        OPT_DEFS += -DEEPROM_EMU_STM32F072xB
        OPT_DEFS += -DSTM32_EEPROM_ENABLE
      else
        # This will effectively work the same as "transient" if not supported by the chip
        SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c
      endif
    else ifeq ($(PLATFORM),ARM_ATSAM)
      SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
    else ifeq ($(PLATFORM),TEST)
      SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
    endif
  endif
endif

ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
    POST_CONFIG_H += $(QUANTUM_DIR)/rgblight_post_config.h
    OPT_DEFS += -DRGBLIGHT_ENABLE
    SRC += $(QUANTUM_DIR)/color.c
    SRC += $(QUANTUM_DIR)/rgblight.c
    CIE1931_CURVE := yes
    LED_BREATHING_TABLE := yes
    RGB_KEYCODES_ENABLE := yes
    ifeq ($(strip $(RGBLIGHT_CUSTOM_DRIVER)), yes)
        OPT_DEFS += -DRGBLIGHT_CUSTOM_DRIVER
    else
        WS2812_DRIVER_REQUIRED := yes
    endif
endif

VALID_MATRIX_TYPES := yes IS31FL3731 IS31FL3733 IS31FL3737 WS2812 custom

LED_MATRIX_ENABLE ?= no
ifneq ($(strip $(LED_MATRIX_ENABLE)), no)
    ifeq ($(filter $(LED_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
        $(error LED_MATRIX_ENABLE="$(LED_MATRIX_ENABLE)" is not a valid matrix type)
    else
        BACKLIGHT_ENABLE = yes
        BACKLIGHT_DRIVER = custom
        OPT_DEFS += -DLED_MATRIX_ENABLE
        SRC += $(QUANTUM_DIR)/led_matrix.c
        SRC += $(QUANTUM_DIR)/led_matrix_drivers.c
    endif
endif

ifeq ($(strip $(LED_MATRIX_ENABLE)), IS31FL3731)
    OPT_DEFS += -DIS31FL3731
    COMMON_VPATH += $(DRIVER_PATH)/issi
    SRC += is31fl3731-simple.c
    QUANTUM_LIB_SRC += i2c_master.c
endif

RGB_MATRIX_ENABLE ?= no

ifneq ($(strip $(RGB_MATRIX_ENABLE)), no)
ifeq ($(filter $(RGB_MATRIX_ENABLE),$(VALID_MATRIX_TYPES)),)
    $(error RGB_MATRIX_ENABLE="$(RGB_MATRIX_ENABLE)" is not a valid matrix type)
endif
    OPT_DEFS += -DRGB_MATRIX_ENABLE
    SRC += $(QUANTUM_DIR)/color.c
    SRC += $(QUANTUM_DIR)/rgb_matrix.c
    SRC += $(QUANTUM_DIR)/rgb_matrix_drivers.c
    CIE1931_CURVE := yes
    RGB_KEYCODES_ENABLE := yes
endif

ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
	RGB_MATRIX_ENABLE := IS31FL3731
endif

ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3731)
    OPT_DEFS += -DIS31FL3731 -DSTM32_I2C -DHAL_USE_I2C=TRUE
    COMMON_VPATH += $(DRIVER_PATH)/issi
    SRC += is31fl3731.c
    QUANTUM_LIB_SRC += i2c_master.c
endif

ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3733)
    OPT_DEFS += -DIS31FL3733 -DSTM32_I2C -DHAL_USE_I2C=TRUE
    COMMON_VPATH += $(DRIVER_PATH)/issi
    SRC += is31fl3733.c
    QUANTUM_LIB_SRC += i2c_master.c
endif

ifeq ($(strip $(RGB_MATRIX_ENABLE)), IS31FL3737)
    OPT_DEFS += -DIS31FL3737 -DSTM32_I2C -DHAL_USE_I2C=TRUE
    COMMON_VPATH += $(DRIVER_PATH)/issi
    SRC += is31fl3737.c
    QUANTUM_LIB_SRC += i2c_master.c
endif

ifeq ($(strip $(RGB_MATRIX_ENABLE)), WS2812)
    OPT_DEFS += -DWS2812
    WS2812_DRIVER_REQUIRED := yes
endif

ifeq ($(strip $(RGB_MATRIX_CUSTOM_KB)), yes)
    OPT_DEFS += -DRGB_MATRIX_CUSTOM_KB
endif

ifeq ($(strip $(RGB_MATRIX_CUSTOM_USER)), yes)
    OPT_DEFS += -DRGB_MATRIX_CUSTOM_USER
endif

ifeq ($(strip $(RGB_KEYCODES_ENABLE)), yes)
    SRC += $(QUANTUM_DIR)/process_keycode/process_rgb.c
endif

ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
    OPT_DEFS += -DTAP_DANCE_ENABLE
    SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
endif

ifeq ($(strip $(KEY_LOCK_ENABLE)), yes)
    OPT_DEFS += -DKEY_LOCK_ENABLE
    SRC += $(QUANTUM_DIR)/process_keycode/process_key_lock.c
endif

ifeq ($(strip $(PRINTING_ENABLE)), yes)
    OPT_DEFS += -DPRINTING_ENABLE
    SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c
    SRC += $(TMK_DIR)/protocol/serial_uart.c
endif

ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
    OPT_DEFS += -DAUTO_SHIFT_ENABLE
    SRC += $(QUANTUM_DIR)/process_keycode/process_auto_shift.c
    ifeq ($(strip $(AUTO_SHIFT_MODIFIERS)), yes)
        OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
    endif
endif

ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
    SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
    OPT_DEFS += $(SERIAL_DEFS)
    VAPTH += $(SERIAL_PATH)
endif

ifneq ($(strip $(VARIABLE_TRACE)),)
    SRC += $(QUANTUM_DIR)/variable_trace.c
    OPT_DEFS += -DNUM_TRACED_VARIABLES=$(strip $(VARIABLE_TRACE))
ifneq ($(strip $(MAX_VARIABLE_TRACE_SIZE)),)
    OPT_DEFS += -DMAX_VARIABLE_TRACE_SIZE=$(strip $(MAX_VARIABLE_TRACE_SIZE))
endif
endif

ifeq ($(strip $(LCD_ENABLE)), yes)
    CIE1931_CURVE := yes
endif

# backward compat
ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
    BACKLIGHT_DRIVER := custom
endif

VALID_BACKLIGHT_TYPES := pwm software custom

BACKLIGHT_ENABLE ?= no
BACKLIGHT_DRIVER ?= pwm
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
    ifeq ($(filter $(BACKLIGHT_DRIVER),$(VALID_BACKLIGHT_TYPES)),)
        $(error BACKLIGHT_DRIVER="$(BACKLIGHT_DRIVER)" is not a valid backlight type)
    endif

    COMMON_VPATH += $(QUANTUM_DIR)/backlight
    SRC += $(QUANTUM_DIR)/backlight/backlight.c
    OPT_DEFS += -DBACKLIGHT_ENABLE

    ifeq ($(strip $(BACKLIGHT_DRIVER)), custom)
        OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
    else ifeq ($(strip $(BACKLIGHT_DRIVER)), software)
        SRC += $(QUANTUM_DIR)/backlight/backlight_soft.c
    else
        ifeq ($(PLATFORM),AVR)
            SRC += $(QUANTUM_DIR)/backlight/backlight_avr.c
        else
            SRC += $(QUANTUM_DIR)/backlight/backlight_arm.c
        endif
    endif
endif

VALID_WS2812_DRIVER_TYPES := bitbang pwm spi i2c

WS2812_DRIVER ?= bitbang
ifeq ($(strip $(WS2812_DRIVER_REQUIRED)), yes)
    ifeq ($(filter $(WS2812_DRIVER),$(VALID_WS2812_DRIVER_TYPES)),)
        $(error WS2812_DRIVER="$(WS2812_DRIVER)" is not a valid WS2812 driver)
    endif

    OPT_DEFS += -DWS2812_DRIVER_$(strip $(shell echo $(WS2812_DRIVER) | tr '[:lower:]' '[:upper:]'))

    ifeq ($(strip $(WS2812_DRIVER)), bitbang)
        SRC += ws2812.c
    else
        SRC += ws2812_$(strip $(WS2812_DRIVER)).c
    endif

    # add extra deps
    ifeq ($(strip $(WS2812_DRIVER)), i2c)
        QUANTUM_LIB_SRC += i2c_master.c
    endif
endif

ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
    CIE1931_CURVE := yes
endif

ifeq ($(strip $(CIE1931_CURVE)), yes)
    OPT_DEFS += -DUSE_CIE1931_CURVE
    LED_TABLES := yes
endif

ifeq ($(strip $(LED_BREATHING_TABLE)), yes)
    OPT_DEFS += -DUSE_LED_BREATHING_TABLE
    LED_TABLES := yes
endif

ifeq ($(strip $(LED_TABLES)), yes)
    SRC += $(QUANTUM_DIR)/led_tables.c
endif

ifeq ($(strip $(TERMINAL_ENABLE)), yes)
    SRC += $(QUANTUM_DIR)/process_keycode/process_terminal.c
    OPT_DEFS += -DTERMINAL_ENABLE
    OPT_DEFS += -DUSER_PRINT
endif

ifeq ($(strip $(USB_HID_ENABLE)), yes)
    include $(TMK_DIR)/protocol/usb_hid.mk
endif

ifeq ($(strip $(ENCODER_ENABLE)), yes)
    SRC += $(QUANTUM_DIR)/encoder.c
    OPT_DEFS += -DENCODER_ENABLE
endif

HAPTIC_ENABLE ?= no
ifneq ($(strip $(HAPTIC_ENABLE)),no)
	COMMON_VPATH += $(DRIVER_PATH)/haptic
	SRC += haptic.c
	OPT_DEFS += -DHAPTIC_ENABLE
endif

ifneq ($(filter DRV2605L, $(HAPTIC_ENABLE)), )
    SRC += DRV2605L.c
    QUANTUM_LIB_SRC += i2c_master.c
    OPT_DEFS += -DDRV2605L
endif

ifneq ($(filter SOLENOID, $(HAPTIC_ENABLE)), )
    SRC += solenoid.c
    OPT_DEFS += -DSOLENOID_ENABLE
endif

ifeq ($(strip $(HD44780_ENABLE)), yes)
    SRC += drivers/avr/hd44780.c
    OPT_DEFS += -DHD44780_ENABLE
endif

ifeq ($(strip $(VELOCIKEY_ENABLE)), yes)
    OPT_DEFS += -DVELOCIKEY_ENABLE
    SRC += $(QUANTUM_DIR)/velocikey.c
endif

ifeq ($(strip $(VIA_ENABLE)), yes)
    DYNAMIC_KEYMAP_ENABLE := yes
    RAW_ENABLE := yes
    BOOTMAGIC_ENABLE := lite
    SRC += $(QUANTUM_DIR)/via.c
    OPT_DEFS += -DVIA_ENABLE
endif

ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes)
    OPT_DEFS += -DDYNAMIC_KEYMAP_ENABLE
    SRC += $(QUANTUM_DIR)/dynamic_keymap.c
endif

ifeq ($(strip $(LEADER_ENABLE)), yes)
  SRC += $(QUANTUM_DIR)/process_keycode/process_leader.c
  OPT_DEFS += -DLEADER_ENABLE
endif


ifeq ($(strip $(DIP_SWITCH_ENABLE)), yes)
  SRC += $(QUANTUM_DIR)/dip_switch.c
  OPT_DEFS += -DDIP_SWITCH_ENABLE
endif

include $(DRIVER_PATH)/qwiic/qwiic.mk

QUANTUM_SRC:= \
    $(QUANTUM_DIR)/quantum.c \
    $(QUANTUM_DIR)/keymap_common.c \
    $(QUANTUM_DIR)/keycode_config.c



VALID_CUSTOM_MATRIX_TYPES:= yes lite no

CUSTOM_MATRIX ?= no

ifneq ($(strip $(CUSTOM_MATRIX)), yes)
    ifeq ($(filter $(CUSTOM_MATRIX),$(VALID_CUSTOM_MATRIX_TYPES)),)
        $(error CUSTOM_MATRIX="$(CUSTOM_MATRIX)" is not a valid custom matrix type)
    endif

    # Include common stuff for all non custom matrix users
    QUANTUM_SRC += $(QUANTUM_DIR)/matrix_common.c

    # if 'lite' then skip the actual matrix implementation
    ifneq ($(strip $(CUSTOM_MATRIX)), lite)
        # Include the standard or split matrix code if needed
        ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
            QUANTUM_SRC += $(QUANTUM_DIR)/split_common/matrix.c
        else
            QUANTUM_SRC += $(QUANTUM_DIR)/matrix.c
        endif
    endif
endif

DEBOUNCE_DIR:= $(QUANTUM_DIR)/debounce
# Debounce Modules. Set DEBOUNCE_TYPE=custom if including one manually.
DEBOUNCE_TYPE?= sym_g
ifneq ($(strip $(DEBOUNCE_TYPE)), custom)
    QUANTUM_SRC += $(DEBOUNCE_DIR)/$(strip $(DEBOUNCE_TYPE)).c
endif

ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
    POST_CONFIG_H += $(QUANTUM_DIR)/split_common/post_config.h
    OPT_DEFS += -DSPLIT_KEYBOARD

    # Include files used by all split keyboards
    QUANTUM_SRC += $(QUANTUM_DIR)/split_common/split_util.c

    # Determine which (if any) transport files are required
    ifneq ($(strip $(SPLIT_TRANSPORT)), custom)
        QUANTUM_SRC += $(QUANTUM_DIR)/split_common/transport.c
        # Functions added via QUANTUM_LIB_SRC are only included in the final binary if they're called.
        # Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
        ifeq ($(PLATFORM),AVR)
            QUANTUM_LIB_SRC += i2c_master.c \
                               i2c_slave.c
        endif

        SERIAL_DRIVER ?= bitbang
        ifeq ($(strip $(SERIAL_DRIVER)), bitbang)
            QUANTUM_LIB_SRC += serial.c
        else
            QUANTUM_LIB_SRC += serial_$(strip $(SERIAL_DRIVER)).c
        endif
    endif
    COMMON_VPATH += $(QUANTUM_PATH)/split_common
endif

ifeq ($(strip $(OLED_DRIVER_ENABLE)), yes)
    OPT_DEFS += -DOLED_DRIVER_ENABLE
    COMMON_VPATH += $(DRIVER_PATH)/oled
    QUANTUM_LIB_SRC += i2c_master.c
    SRC += oled_driver.c
endif

SPACE_CADET_ENABLE ?= yes
ifeq ($(strip $(SPACE_CADET_ENABLE)), yes)
  SRC += $(QUANTUM_DIR)/process_keycode/process_space_cadet.c
  OPT_DEFS += -DSPACE_CADET_ENABLE
endif

MAGIC_ENABLE ?= yes
ifeq ($(strip $(MAGIC_ENABLE)), yes)
    SRC += $(QUANTUM_DIR)/process_keycode/process_magic.c
    OPT_DEFS += -DMAGIC_KEYCODE_ENABLE
endif

GRAVE_ESC_ENABLE ?= yes
ifeq ($(strip $(GRAVE_ESC_ENABLE)), yes)
    SRC += $(QUANTUM_DIR)/process_keycode/process_grave_esc.c
    OPT_DEFS += -DGRAVE_ESC_ENABLE
endif

ifeq ($(strip $(DYNAMIC_MACRO_ENABLE)), yes)
    SRC += $(QUANTUM_DIR)/process_keycode/process_dynamic_macro.c
    OPT_DEFS += -DDYNAMIC_MACRO_ENABLE
endif