diff options
| -rw-r--r-- | xmake/rules/verilator/verilator.lua | 194 | ||||
| -rw-r--r-- | xmake/rules/verilator/xmake.lua | 174 |
2 files changed, 203 insertions, 165 deletions
diff --git a/xmake/rules/verilator/verilator.lua b/xmake/rules/verilator/verilator.lua new file mode 100644 index 000000000..e3984d200 --- /dev/null +++ b/xmake/rules/verilator/verilator.lua @@ -0,0 +1,194 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the 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. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki +-- @file verilator.lua +-- + +function config(target) + local toolchain = assert(target:toolchain("verilator"), 'we need set_toolchains("verilator") in target("%s")', target:name()) + local verilator = assert(toolchain:config("verilator"), "verilator not found!") + local autogendir = path.join(target:autogendir(), "rules", "verilator") + local tmpdir = os.tmpfile() .. ".dir" + local cmakefile = path.join(tmpdir, "test.cmake") + local sourcefile = path.join(tmpdir, "main.v") + local argv = {"--cc", "--make", "cmake", "--prefix", "test", "--Mdir", tmpdir, sourcefile} + local flags = target:values("verilator.flags") + if flags then + table.join2(argv, flags) + end + io.writefile(sourcefile, [[ +module hello; +initial begin +$display("hello world!"); +$finish ; +end +endmodule]]) + os.mkdir(tmpdir) + os.runv(verilator, argv) + + -- parse some configurations from cmakefile + local verilator_root + local switches = {} + local targetname = target:name() + io.gsub(cmakefile, "set%((%S-) (.-)%)", function (key, values) + if key == "VERILATOR_ROOT" then + verilator_root = values:match("\"(.-)\" CACHE PATH") + if not verilator_root then + verilator_root = values:match("(.-) CACHE PATH") + end + elseif key == "test_SC" then + -- SystemC output mode? 0/1 (from --sc) + switches.SC = values:trim() + elseif key == "test_COVERAGE" then + -- Coverage output mode? 0/1 (from --coverage) + switches.COVERAGE = values:trim() + elseif key == "test_TIMING" then + -- Timing mode? 0/1 (from --timing) + switches.TIMING = values:trim() + elseif key == "test_THREADS" then + -- Threaded output mode? 1/N threads (from --threads) + switches.THREADS = values:trim() + elseif key == "test_TRACE_VCD" then + -- VCD Tracing output mode? 0/1 (from --trace) + switches.TRACE_VCD = values:trim() + elseif key == "test_TRACE_FST" then + -- FST Tracing output mode? 0/1 (from --trace-fst) + switches.TRACE_FST = values:trim() + end + + end) + assert(verilator_root, "the verilator root directory not found!") + target:data_set("verilator.root", verilator_root) + + -- add includedirs + if not os.isfile(autogendir) then + os.mkdir(autogendir) + end + target:add("includedirs", autogendir) + target:add("includedirs", path.join(verilator_root, "include")) + target:add("includedirs", path.join(verilator_root, "include", "vltstd")) + + -- set languages + local languages = target:get("languages") + local cxxlang = false + for _, lang in ipairs(languages) do + if lang:startswith("xx") or lang:startswith("++") then + cxxlang = true + break + end + end + if not cxxlang then + target:set("languages", "c++20") + end + + -- add defines for switches + for k, v in pairs(switches) do + target:add("defines", "VM_" .. k .. "=" .. v) + end + + -- add syslinks + if target:is_plat("linux", "macosx") and switches.THREADS == "1" then + target:add("syslinks", "pthread") + end + + os.rm(tmpdir) +end + +function buildcmd_vfiles(target, batchcmds, sourcebatch, opt) + local toolchain = assert(target:toolchain("verilator"), 'we need set_toolchains("verilator") in target("%s")', target:name()) + local verilator = assert(toolchain:config("verilator"), "verilator not found!") + local autogendir = path.join(target:autogendir(), "rules", "verilator") + local targetname = target:name() + local cmakefile = path.join(autogendir, targetname .. ".cmake") + local dependfile = cmakefile .. ".d" + + local argv = {"--cc", "--make", "cmake", "--prefix", targetname, "--Mdir", path(autogendir)} + local flags = target:values("verilator.flags") + if flags then + table.join2(argv, flags) + end + local sourcefiles = sourcebatch.sourcefiles + for _, sourcefile in ipairs(sourcefiles) do + batchcmds:show_progress(opt.progress, "${color.build.object}compiling.verilog %s", path.filename(sourcefile)) + end + table.join2(argv, sourcefiles) + + -- generate c++ sourcefiles + batchcmds:vrunv(verilator, argv) + batchcmds:add_depfiles(sourcefiles) + batchcmds:set_depmtime(os.mtime(cmakefile)) + batchcmds:set_depcache(dependfile) +end + +function buildcmd_cppfiles(target, batchcmds, sourcebatch, opt) + local toolchain = assert(target:toolchain("verilator"), 'we need set_toolchains("verilator") in target("%s")', target:name()) + local verilator = assert(toolchain:config("verilator"), "verilator not found!") + local autogendir = path.join(target:autogendir(), "rules", "verilator") + local targetname = target:name() + local cmakefile = path.join(autogendir, targetname .. ".cmake") + local dependfile = path.join(autogendir, targetname .. ".build.d") + local verilator_root = assert(target:data("verilator.root"), "no verilator_root!") + + -- parse some configurations from cmakefile + local global_classes = {} + local classefiles_slow = {} + local classefiles_fast = {} + local supportfiles_slow = {} + local supportfiles_fast = {} + io.gsub(cmakefile, "set%((%S-) (.-)%)", function (key, values) + if key == targetname .. "_GLOBAL" then + -- get global class source files + -- set(hello_GLOBAL "${VERILATOR_ROOT}/include/verilated.cpp" "${VERILATOR_ROOT}/include/verilated_threads.cpp") + for classfile in values:gmatch("\"(.-)\"") do + classfile = classfile:gsub("%${VERILATOR_ROOT}", verilator_root) + if os.isfile(classfile) then + table.insert(global_classes, classfile) + end + end + elseif key == targetname .. "_CLASSES_SLOW" then + for classfile in values:gmatch("\"(.-)\"") do + table.insert(classefiles_slow, classfile) + end + elseif key == targetname .. "_CLASSES_FAST" then + for classfile in values:gmatch("\"(.-)\"") do + table.insert(classefiles_fast, classfile) + end + elseif key == targetname .. "_SUPPORT_SLOW" then + for classfile in values:gmatch("\"(.-)\"") do + table.insert(supportfiles_slow, classfile) + end + elseif key == targetname .. "_SUPPORT_FAST" then + for classfile in values:gmatch("\"(.-)\"") do + table.insert(supportfiles_fast, classfile) + end + end + end) + + -- get compiled source files + local sourcefiles = table.join(global_classes, classefiles_slow, classefiles_fast, supportfiles_slow, supportfiles_fast) + + -- do build + for _, sourcefile in ipairs(sourcefiles) do + local objectfile = target:objectfile(sourcefile) + batchcmds:show_progress(opt.progress, "${color.build.object}compiling.$(mode) %s", path.filename(sourcefile)) + batchcmds:compile(sourcefile, objectfile) + table.insert(target:objectfiles(), objectfile) + end + batchcmds:add_depfiles(sourcefiles) + batchcmds:set_depmtime(os.mtime(dependfile)) + batchcmds:set_depcache(dependfile) +end diff --git a/xmake/rules/verilator/xmake.lua b/xmake/rules/verilator/xmake.lua index f5904bd32..eb79807be 100644 --- a/xmake/rules/verilator/xmake.lua +++ b/xmake/rules/verilator/xmake.lua @@ -26,177 +26,21 @@ rule("verilator.binary") end) on_config(function (target) - local toolchain = assert(target:toolchain("verilator"), 'we need set_toolchains("verilator") in target("%s")', target:name()) - local verilator = assert(toolchain:config("verilator"), "verilator not found!") - local autogendir = path.join(target:autogendir(), "rules", "verilator") - local tmpdir = os.tmpfile() .. ".dir" - local cmakefile = path.join(tmpdir, "test.cmake") - local sourcefile = path.join(tmpdir, "main.v") - local argv = {"--cc", "--make", "cmake", "--prefix", "test", "--Mdir", tmpdir, sourcefile} - local flags = target:values("verilator.flags") - if flags then - table.join2(argv, flags) - end - io.writefile(sourcefile, [[ -module hello; - initial begin - $display("hello world!"); - $finish ; - end -endmodule]]) - os.mkdir(tmpdir) - os.runv(verilator, argv) - - -- parse some configurations from cmakefile - local verilator_root - local switches = {} - local targetname = target:name() - io.gsub(cmakefile, "set%((%S-) (.-)%)", function (key, values) - if key == "VERILATOR_ROOT" then - verilator_root = values:match("\"(.-)\" CACHE PATH") - if not verilator_root then - verilator_root = values:match("(.-) CACHE PATH") - end - elseif key == "test_SC" then - -- SystemC output mode? 0/1 (from --sc) - switches.SC = values:trim() - elseif key == "test_COVERAGE" then - -- Coverage output mode? 0/1 (from --coverage) - switches.COVERAGE = values:trim() - elseif key == "test_TIMING" then - -- Timing mode? 0/1 (from --timing) - switches.TIMING = values:trim() - elseif key == "test_THREADS" then - -- Threaded output mode? 1/N threads (from --threads) - switches.THREADS = values:trim() - elseif key == "test_TRACE_VCD" then - -- VCD Tracing output mode? 0/1 (from --trace) - switches.TRACE_VCD = values:trim() - elseif key == "test_TRACE_FST" then - -- FST Tracing output mode? 0/1 (from --trace-fst) - switches.TRACE_FST = values:trim() - end - - end) - assert(verilator_root, "the verilator root directory not found!") - target:data_set("verilator.root", verilator_root) - - -- add includedirs - if not os.isfile(autogendir) then - os.mkdir(autogendir) - end - target:add("includedirs", autogendir) - target:add("includedirs", path.join(verilator_root, "include")) - target:add("includedirs", path.join(verilator_root, "include", "vltstd")) - - -- set languages - local languages = target:get("languages") - local cxxlang = false - for _, lang in ipairs(languages) do - if lang:startswith("xx") or lang:startswith("++") then - cxxlang = true - break - end - end - if not cxxlang then - target:set("languages", "c++20") - end - - -- add defines for switches - for k, v in pairs(switches) do - target:add("defines", "VM_" .. k .. "=" .. v) - end - - -- add syslinks - if target:is_plat("linux", "macosx") and switches.THREADS == "1" then - target:add("syslinks", "pthread") - end - - os.rm(tmpdir) + import("verilator").config(target) end) before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) - local toolchain = assert(target:toolchain("verilator"), 'we need set_toolchains("verilator") in target("%s")', target:name()) - local verilator = assert(toolchain:config("verilator"), "verilator not found!") - local autogendir = path.join(target:autogendir(), "rules", "verilator") - local targetname = target:name() - local cmakefile = path.join(autogendir, targetname .. ".cmake") - local dependfile = cmakefile .. ".d" - - local argv = {"--cc", "--make", "cmake", "--prefix", targetname, "--Mdir", path(autogendir)} - local flags = target:values("verilator.flags") - if flags then - table.join2(argv, flags) - end - local sourcefiles = sourcebatch.sourcefiles - for _, sourcefile in ipairs(sourcefiles) do - batchcmds:show_progress(opt.progress, "${color.build.object}compiling.verilator %s", path.filename(sourcefile)) - end - table.join2(argv, sourcefiles) - - -- generate c++ sourcefiles - batchcmds:vrunv(verilator, argv) - batchcmds:add_depfiles(sourcefiles) - batchcmds:set_depmtime(os.mtime(cmakefile)) - batchcmds:set_depcache(dependfile) + import("verilator").buildcmd_vfiles(target, batchcmds, sourcebatch, opt) end) - on_buildcmd_files(function (target, batchcmds, sourcebatch, opt) - local toolchain = assert(target:toolchain("verilator"), 'we need set_toolchains("verilator") in target("%s")', target:name()) - local verilator = assert(toolchain:config("verilator"), "verilator not found!") - local autogendir = path.join(target:autogendir(), "rules", "verilator") - local targetname = target:name() - local cmakefile = path.join(autogendir, targetname .. ".cmake") - local dependfile = path.join(autogendir, targetname .. ".build.d") - local verilator_root = assert(target:data("verilator.root"), "no verilator_root!") - - -- parse some configurations from cmakefile - local global_classes = {} - local classefiles_slow = {} - local classefiles_fast = {} - local supportfiles_slow = {} - local supportfiles_fast = {} - io.gsub(cmakefile, "set%((%S-) (.-)%)", function (key, values) - if key == targetname .. "_GLOBAL" then - -- get global class source files - -- set(hello_GLOBAL "${VERILATOR_ROOT}/include/verilated.cpp" "${VERILATOR_ROOT}/include/verilated_threads.cpp") - for classfile in values:gmatch("\"(.-)\"") do - classfile = classfile:gsub("%${VERILATOR_ROOT}", verilator_root) - if os.isfile(classfile) then - table.insert(global_classes, classfile) - end - end - elseif key == targetname .. "_CLASSES_SLOW" then - for classfile in values:gmatch("\"(.-)\"") do - table.insert(classefiles_slow, classfile) - end - elseif key == targetname .. "_CLASSES_FAST" then - for classfile in values:gmatch("\"(.-)\"") do - table.insert(classefiles_fast, classfile) - end - elseif key == targetname .. "_SUPPORT_SLOW" then - for classfile in values:gmatch("\"(.-)\"") do - table.insert(supportfiles_slow, classfile) - end - elseif key == targetname .. "_SUPPORT_FAST" then - for classfile in values:gmatch("\"(.-)\"") do - table.insert(supportfiles_fast, classfile) - end - end - end) + --[[ + on_build_files(function (target, batchjobs, sourcebatch, opt) + import("private.action.build.object", {alias = "build_object_batchjobs"}) - -- get compiled source files - local sourcefiles = table.join(global_classes, classefiles_slow, classefiles_fast, supportfiles_slow, supportfiles_fast) + end, {batch = true, distcc = true}) + ]] - -- do build - for _, sourcefile in ipairs(sourcefiles) do - local objectfile = target:objectfile(sourcefile) - batchcmds:show_progress(opt.progress, "${color.build.object}compiling.$(mode) %s", path.filename(sourcefile)) - batchcmds:compile(sourcefile, objectfile) - table.insert(target:objectfiles(), objectfile) - end - batchcmds:add_depfiles(sourcefiles) - batchcmds:set_depmtime(os.mtime(dependfile)) - batchcmds:set_depcache(dependfile) + on_buildcmd_files(function (target, batchcmds, sourcebatch, opt) + import("verilator").buildcmd_cppfiles(target, batchcmds, sourcebatch, opt) end) |
