Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
env:
VERIBLE_VERSION: v0.0-4007-g98bdb38a
BUILD_XSPCOMM_SWIG: python,java
VERILATOR_VERSION: v5.018
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down Expand Up @@ -61,17 +62,44 @@ jobs:
rm -rf /tmp/swig

- name: Build and install Verilator from source
env:
VERILATOR_VERSION: v5.018
id: setup-verilator
run: |
set -euo pipefail
echo "VERILATOR_PREFIX=${HOME}/.cache/verilator/${VERILATOR_VERSION}" >> "$GITHUB_ENV"

- name: Restore Verilator fakeroot cache
id: cache-verilator
uses: actions/cache/restore@v4
with:
path: ~/.cache/verilator/${{ env.VERILATOR_VERSION }}
key: verilator-${{ matrix.os }}-${{ env.VERILATOR_VERSION }}-v1

- name: Use cached Verilator (if available)
if: steps.cache-verilator.outputs.cache-hit == 'true'
run: |
echo "${VERILATOR_PREFIX}/bin" >> "$GITHUB_PATH"
verilator --version || true

- name: Build and install Verilator into fakeroot
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
set -euo pipefail
git clone https://github.com/verilator/verilator -b "${VERILATOR_VERSION}" --depth=1 /tmp/verilator
cd /tmp/verilator
autoconf
./configure --prefix=/usr/local
./configure --prefix="${VERILATOR_PREFIX}"
make -j"$(nproc)"
sudo make install
make install
rm -rf /tmp/verilator
echo "${VERILATOR_PREFIX}/bin" >> "$GITHUB_PATH"
verilator --version || true

- name: Save Verilator fakeroot cache (trusted contexts only)
if: steps.cache-verilator.outputs.cache-hit != 'true' && github.event_name == 'push'
uses: actions/cache/save@v4
with:
path: ~/.cache/verilator/${{ env.VERILATOR_VERSION }}
key: verilator-${{ matrix.os }}-${{ env.VERILATOR_VERSION }}-v1

- name: Install Verible (format + syntax)
run: |
Expand Down
43 changes: 28 additions & 15 deletions include/picker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,42 +105,52 @@ inline std::string trim(std::string s, std::string p)
{
if (s.empty()) { return s; }
s.erase(0, s.find_first_not_of(p));
s.erase(s.find_last_not_of(p) + p.size());
size_t pos = s.find_last_not_of(p);
if (pos != std::string::npos) { s.erase(pos + 1); }
return s;
}

inline std::string ltrim(std::string s)
{
if (s.empty()) { return s; }
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
return s;
}

inline std::string rtrim(std::string s)
{
if (s.empty()) { return s; }
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
return s;
}

inline std::string trim(std::string s)
{
if (s.empty()) { return s; }
return rtrim(ltrim(s));
}

inline std::vector<std::string> strsplit(std::string str, std::string s = " ")
{
std::vector<std::string> ret;
int start = 0;
int end = str.find(s);
while (end != -1) {
std::cout << "strsplit: '" << str << "' by '" << s << "'" << std::endl;
std::vector<std::string> ret = {};
if (s.empty()) {
auto token = trim(str);
if (!token.empty()) ret.push_back(token);
return ret;
}
size_t start = 0;
size_t end = str.find(s);
while (end != std::string::npos) {
auto sub = str.substr(start, end - start);
trim(sub);
ret.push_back(sub);
sub = trim(sub);
if (!sub.empty()) ret.push_back(sub);
start = end + s.size();
end = str.find(s, start);
}
auto sub = str.substr(start, end - start);
trim(sub);
ret.push_back(sub);
auto sub = str.substr(start);
sub = trim(sub);
if (!sub.empty()) ret.push_back(sub);
return ret;
}

Expand Down Expand Up @@ -393,7 +403,10 @@ inline std::string read_params(std::string fname)
if (ifile.is_open()) {
std::string line_txt;
while (std::getline(ifile, line_txt)) {
line_txt = trim(strsplit(line_txt, "#").front());
// Remove comments (anything after '#') and trim
auto hash_pos = line_txt.find('#');
if (hash_pos != std::string::npos) { line_txt.erase(hash_pos); }
line_txt = trim(line_txt);
if (line_txt.empty()) { continue; }
if (ret.empty()) {
ret = line_txt;
Expand Down Expand Up @@ -508,10 +521,10 @@ inline std::string get_template_path()
}
auto path = get_executable_path();
auto tmp = get_target_path_from(path, {"../../../template", // 1. search in source dir (for dev)
"./template", // 2. search in current dir
"../../share/picker/template", // 3. search in share dir (for install)
"/usr/local/share/picker/template", // 4. search in /usr/local/share
"/etc/picker/template"}); // 5. search in /etc
"./template", // 2. search in current dir
"../../share/picker/template", // 3. search in share dir (for install)
"/usr/local/share/picker/template", // 4. search in /usr/local/share
"/etc/picker/template"}); // 5. search in /etc
if (!tmp.empty()) { return tmp; }
PK_FATAL("template not found, please check the installation or manually set the source dir path");
}
Expand Down
67 changes: 40 additions & 27 deletions src/parser/firrtl.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

#include "parser/firrtl.hpp"
#include <fstream>
#include <sstream>
Expand Down Expand Up @@ -220,57 +219,71 @@ namespace picker { namespace parser {
std::string main_module_name;
std::vector<sv_signal_define> ports;

bool found_main_module = false;
bool in_main_module = false;
bool parsing_ports = false;

// Parse FIRRTL file line by line
while (std::getline(file, line)) {
// Remove leading/trailing whitespace
line = std::regex_replace(line, std::regex(R"(^\s+|\s+$)"), "");

if (line.empty() || line[0] == ';') continue; // Skip empty lines and comments

// Parse circuit declaration: "circuit MyCircuit :"
std::regex circuit_regex(R"(circuit\s+(\w+)\s*:)");
std::smatch circuit_match;
if (std::regex_search(line, circuit_match, circuit_regex)) {
circuit_name = circuit_match[1].str();
if (!found_main_module) {
size_t pos = line.find("circuit ");
if (pos == std::string::npos)
continue;
pos += 8;
auto end = line.find(' ', pos);
auto len = end - pos;
circuit_name = line.substr(pos, len);
main_module_name = circuit_name; // Main module typically has same name as circuit
found_main_module = true;
PK_MESSAGE("Found circuit: %s", circuit_name.c_str());
continue;
}

}
// Parse module declaration: "module MyModule :"
std::regex module_regex(R"(module\s+(\w+)\s*:)");
std::smatch module_match;
if (std::regex_search(line, module_match, module_regex)) {
std::string module_name = module_match[1].str();

// Check if this is the main module (same name as circuit)
else if (!in_main_module) {
auto pos = line.find("module ");
// No module define in this line.
if (pos == std::string::npos)
continue;
pos += 7;
auto end = line.find(' ', pos);
auto len = end - pos;
auto module_name = line.substr(pos, len);
// Check if this is the main module (same name as circuit)
if (module_name == circuit_name) {
in_main_module = true;
parsing_ports = true;
PK_MESSAGE("Found main module: %s", module_name.c_str());
} else {
in_main_module = false;
parsing_ports = false;
}
continue;
}

// Parse ports in main module
if (in_main_module && parsing_ports) {
else if (in_main_module && parsing_ports) {
// Check for port lines: "input clock : Clock" or "output result : UInt<32>"
if (line.find("input ") == 0 || line.find("output ") == 0) {
std::vector<sv_signal_define> parsed_ports = parse_firrtl_port(line);
auto input_pos = line.find("input ");
auto output_pos = line.find("output ");
size_t pos;
if (input_pos != std::string::npos && output_pos != std::string::npos) {
pos = std::min(input_pos, output_pos);
} else if (input_pos != std::string::npos) {
pos = input_pos;
} else if (output_pos != std::string::npos) {
pos = output_pos;
} else {
pos = std::string::npos;
}
if (pos != std::string::npos) {
auto parse_line = line.substr(pos);
PK_MESSAGE("Find: %s", parse_line.c_str());
std::vector<sv_signal_define> parsed_ports = parse_firrtl_port(parse_line);
for (const auto& port : parsed_ports) {
if (!port.logic_pin.empty()) {
ports.push_back(port);
}
}
}
// Stop parsing ports when we hit non-port content
else if (!line.empty() && line.find("input ") != 0 && line.find("output ") != 0) {
else if (!line.empty()) {
parsing_ports = false;
}
}
Expand Down
7 changes: 4 additions & 3 deletions template/lib/cmake/gsim.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ if(SIMULATOR STREQUAL "gsim")
add_definitions(-DUSE_GSIM)
add_definitions(-DNO_SV_VPI)
message(STATUS "gsim simulator generate source files")
set(SIMULATOR_FLAGS "$ENV{GSIM_FLAGS}")
string(REPLACE ";" " " GSIM_FLAGS "$ENV{SIMULATOR_FLAGS}")
separate_arguments(GSIM_FLAG_LIST UNIX_COMMAND "${GSIM_FLAGS}")
# find cmd gsim and generate source files
find_program(GSIM_EXECUTABLE gsim)
if(NOT GSIM_EXECUTABLE)
Expand All @@ -15,7 +16,7 @@ if(SIMULATOR STREQUAL "gsim")
execute_process(
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND
${GSIM_EXECUTABLE} ${SIMULATOR_FLAGS} --dir=_SRC
${GSIM_EXECUTABLE} ${GSIM_FLAG_LIST} --dir=_SRC
${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}.fir
COMMAND_ECHO STDOUT
)
Expand Down Expand Up @@ -61,4 +62,4 @@ if(SIMULATOR STREQUAL "gsim")
${GMP_LIBRARIES}
)

endif()
endif()
2 changes: 1 addition & 1 deletion test/test_picker_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int main() {
assert(picker::ltrim(string(" hi")) == "hi");
assert(picker::rtrim(string("hi ")) == "hi");
assert(picker::trim(string(" hi \t")) == "hi");
assert(picker::trim(string("--x--"), string("-")) == string("x--"));
assert(picker::trim(string("--x--"), string("-")) == string("x"));

// strsplit basic
auto ss = picker::strsplit(string("a b c"));
Expand Down