Update format to SystemVerilog Module
This commit is contained in:
@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 20)
|
|||||||
|
|
||||||
find_package(Boost 1.81 COMPONENTS program_options REQUIRED)
|
find_package(Boost 1.81 COMPONENTS program_options REQUIRED)
|
||||||
|
|
||||||
add_executable(lasm
|
add_executable(svrasm
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/lexer/Token.cpp
|
src/lexer/Token.cpp
|
||||||
src/lexer/Lexer.cpp
|
src/lexer/Lexer.cpp
|
||||||
@ -25,4 +25,4 @@ add_executable(lasm
|
|||||||
src/codegen/CodegenObserver.cpp
|
src/codegen/CodegenObserver.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(lasm Boost::program_options)
|
target_link_libraries(svrasm Boost::program_options)
|
@ -3,8 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "CodegenObserver.h"
|
#include "CodegenObserver.h"
|
||||||
#include <boost/format.hpp>
|
#include <bitset>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
CodegenObserver::CodegenObserver(const Node &node, std::vector<std::string> &output_string)
|
CodegenObserver::CodegenObserver(const Node &node, std::vector<std::string> &output_string)
|
||||||
: PostfixObserver(node), output_string(output_string) {}
|
: PostfixObserver(node), output_string(output_string) {}
|
||||||
@ -13,12 +12,13 @@ void CodegenObserver::action(const Node &node) {
|
|||||||
const uint8_t dec = node.compile();
|
const uint8_t dec = node.compile();
|
||||||
const uint8_t INVALID = -1;
|
const uint8_t INVALID = -1;
|
||||||
|
|
||||||
|
// TODO: Don't do the conversion to binary here, but in generator module
|
||||||
if (dec != INVALID) {
|
if (dec != INVALID) {
|
||||||
// uint8_t is always interpreted as char, so cast to uint32_t
|
// uint8_t is always interpreted as char, so cast to uint32_t
|
||||||
const std::string hex = (boost::format("%x") % static_cast<uint32_t>(dec)).str();
|
const std::string bin = std::bitset<8>(dec).to_string();
|
||||||
if (hex.empty() || hex.size() > 2) {
|
if (bin.empty() || bin.size() > 8) {
|
||||||
throw "Compile Error: Resulting instruction has invalid size!";
|
throw "Compile Error: Resulting instruction has invalid size!";
|
||||||
}
|
}
|
||||||
output_string.push_back(hex.length() == 2 ? hex : "0" + hex);
|
output_string.push_back(bin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
52
src/main.cpp
52
src/main.cpp
@ -1,19 +1,19 @@
|
|||||||
#include <iostream>
|
#include "ast/Node.h"
|
||||||
|
#include "codegen/CodegenObserver.h"
|
||||||
|
#include "codegen/PrintObserver.h"
|
||||||
|
#include "lexer/Lexer.h"
|
||||||
|
#include "parser/Parser.h"
|
||||||
|
#include <bitset>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/program_options.hpp>
|
|
||||||
#include <boost/format.hpp>
|
|
||||||
#include <iomanip>
|
|
||||||
#include "lexer/Lexer.h"
|
|
||||||
#include "ast/Node.h"
|
|
||||||
#include "parser/Parser.h"
|
|
||||||
#include "codegen/PrintObserver.h"
|
|
||||||
#include "codegen/CodegenObserver.h"
|
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
auto read(const std::string& input_file, std::string &input_string) -> bool {
|
auto read(const std::string &input_file, std::string &input_string) -> bool {
|
||||||
std::ifstream ifs;
|
std::ifstream ifs;
|
||||||
ifs.open(input_file, std::ios_base::in);
|
ifs.open(input_file, std::ios_base::in);
|
||||||
if (!ifs) {
|
if (!ifs) {
|
||||||
@ -54,6 +54,7 @@ auto parse(std::vector<Token> &tokens) -> std::unique_ptr<Node> {
|
|||||||
return std::move(parser.parse());
|
return std::move(parser.parse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Modularize the output generation, I want different generators for different formats
|
||||||
auto write(const std::string &output_file, const std::vector<std::string> &output_string) -> bool {
|
auto write(const std::string &output_file, const std::vector<std::string> &output_string) -> bool {
|
||||||
if (output_string.size() > 255) {
|
if (output_string.size() > 255) {
|
||||||
std::cout << "Program too large!" << std::endl;
|
std::cout << "Program too large!" << std::endl;
|
||||||
@ -67,22 +68,26 @@ auto write(const std::string &output_file, const std::vector<std::string> &outpu
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs << "v3.0 hex words addressed";
|
ofs << "`default_nettype none\n\n"
|
||||||
for (uint32_t i = 0; i <= 255; ++i) {
|
|
||||||
if (i % 16 == 0) {
|
|
||||||
ofs << std::endl;
|
|
||||||
// Print Address
|
|
||||||
std::string address = (boost::format("%x") % i).str();
|
|
||||||
ofs << (address == "0" ? "00" : address) << ": ";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<< "module ROM(\n"
|
||||||
|
<< " input var logic[7:0] address,\n"
|
||||||
|
<< " output var logic[7:0] dataout\n"
|
||||||
|
<< ");\n\n"
|
||||||
|
|
||||||
|
<< " always @(address) case (address)\n";
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i <= 255; ++i) {
|
||||||
if (i < output_string.size()) {
|
if (i < output_string.size()) {
|
||||||
ofs << output_string[i] << " ";
|
ofs << " case 8'b" << std::bitset<8>(i).to_string() << ": dataout = 8'b" << output_string[i] << ";\n";
|
||||||
} else {
|
|
||||||
ofs << "00 ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ofs << " default: dataout = 8'b00000000;\n"
|
||||||
|
<< " endcase\n\n"
|
||||||
|
|
||||||
|
<< "endmodule" << std::endl;
|
||||||
|
|
||||||
ofs.flush();
|
ofs.flush();
|
||||||
ofs.close();
|
ofs.close();
|
||||||
return true;
|
return true;
|
||||||
@ -91,10 +96,7 @@ auto write(const std::string &output_file, const std::vector<std::string> &outpu
|
|||||||
auto main(int argc, char **argv) -> int {
|
auto main(int argc, char **argv) -> int {
|
||||||
// Argument parsing straight from the Boost manual: https://www.boost.org/doc/libs/1_60_0/doc/html/program_options/tutorial.html
|
// Argument parsing straight from the Boost manual: https://www.boost.org/doc/libs/1_60_0/doc/html/program_options/tutorial.html
|
||||||
po::options_description desc("Allowed options");
|
po::options_description desc("Allowed options");
|
||||||
desc.add_options()
|
desc.add_options()("help,h", "Show this help message")("input,i", po::value<std::string>(), "Input file")("output,o", po::value<std::string>(), "Output file");
|
||||||
("help,h", "Show this help message")
|
|
||||||
("input,i", po::value<std::string>(), "Input file")
|
|
||||||
("output,o", po::value<std::string>(), "Output file");
|
|
||||||
|
|
||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||||
|
Reference in New Issue
Block a user